//This product is provided under the terms of EPL (Eclipse Public License)
//version 1.0.
//
//The full license text can be read from: http://www.eclipse.org/org/documents/epl-v10.php
package org.dtangler.ui.dsm.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dtangler.core.analysisresult.AnalysisResult;
import org.dtangler.core.analysisresult.Violation.Severity;
import org.dtangler.core.dependencies.Dependable;
import org.dtangler.core.dependencies.Dependency;
import org.dtangler.core.dsm.Dsm;
import org.dtangler.core.dsm.DsmCell;
import org.dtangler.core.dsm.DsmRow;
import org.dtangler.ui.dsm.CellInfo;
import org.dtangler.ui.dsm.DependableInfo;
import org.dtangler.ui.dsm.DsmGuiModel;
import org.dtangler.ui.dsm.DsmGuiModelChangeListener;
import org.dtangler.ui.dsm.NullCellInfo;
public class DsmGuiModelImpl implements DsmGuiModel, ColumnAndRowSelectionModel {
private final List<DsmGuiModelChangeListener> listeners = new ArrayList();
private Formatter displayNameFormatter;
private DisplayNameFormat displayNameFormat = DisplayNameFormat.full;
private Dsm dsm;
private AnalysisResult analysisResult;
private List<Integer> selectedRows = Collections.EMPTY_LIST;
private List<Integer> selectedCols = Collections.EMPTY_LIST;
private int crossHairRow = -1;
private int crossHairCol = -1;
private final Map<Integer, Map<Integer, CellInfo>> cellInfoCache = new HashMap();
public CellInfo getCellInfo(final int row, final int col) {
Map<Integer, CellInfo> rowCache = cellInfoCache.get(row);
if (rowCache == null) {
rowCache = new HashMap<Integer, CellInfo>();
cellInfoCache.put(row, rowCache);
}
CellInfo cellInfo = rowCache.get(col);
if (cellInfo == null) {
cellInfo = createCellInfo(row, col);
rowCache.put(col, cellInfo);
}
return cellInfo;
}
private CellInfo createCellInfo(final int row, final int col) {
DsmCell dsmCell = getDsmCell(row, col);
if (!dsmCell.isValid())
return NullCellInfo.instance;
Dependency dependency = dsm.getRows().get(row).getCells().get(col)
.getDependency();
return new CellInfoImpl(dsmCell, new AnalysisResultInfoImpl(
hasViolations(dependency, Severity.error), hasViolations(
dependency, Severity.warning)), row, col, this);
}
private boolean hasViolations(Dependency dependency, Severity severity) {
return !analysisResult.getViolations(dependency, severity).isEmpty();
}
private boolean containsViolations(Dependable dependable, Severity severity) {
return !analysisResult.getChildViolations(dependable, severity)
.isEmpty();
}
public boolean isRowOrColumnInCrossHair(final int row, final int col) {
if (multiCellSelectionExists())
return false;
return crossHairRow == row || crossHairCol == col;
}
public int getColumnCount() {
return getRowCount();
}
public DependableInfo getColumnInfo(int index) {
return createDependableInfo(index, false);
}
public DependableInfo getRowInfo(int index) {
boolean isSelected = selectedRows.contains(index)
&& selectedCols.isEmpty();
return createDependableInfo(index, isSelected);
}
private DependableInfo createDependableInfo(int index, boolean isSelected) {
boolean isInCrossHair = isInCrosshair(index);
DsmRow dsmRow = dsm.getRows().get(index);
return new DependableInfoImpl(dsmRow, index + 1, isInCrossHair,
isSelected, containsViolations(dsmRow.getDependee(),
Severity.error), containsViolations(dsmRow
.getDependee(), Severity.warning),
getDisplayNameFormatter());
}
private boolean isInCrosshair(final int index) {
if (multiCellSelectionExists())
return false;
return crossHairCol == index || crossHairRow == index;
}
private boolean multiCellSelectionExists() {
return selectedCols.size() != 1 || selectedRows.size() != 1;
}
private DsmCell getDsmCell(int row, int col) {
return dsm.getRows().get(row).getCells().get(col);
}
public int getRowCount() {
if (dsm == null)
return 0;
return dsm.getRows().size();
}
public void selectCells(List<Integer> rows, List<Integer> cols) {
this.selectedRows = rows;
this.selectedCols = cols;
if (!rows.isEmpty())
this.crossHairRow = rows.get(0).intValue();
else
this.crossHairRow = -1;
if (!cols.isEmpty())
this.crossHairCol = cols.get(0).intValue();
else
this.crossHairCol = -1;
fireDsmGuiModelChanged();
}
public List<Integer> getSelectedRows() {
return this.selectedRows;
}
public List<Integer> getSelectedCols() {
return this.selectedCols;
}
private void fireDsmGuiModelChanged() {
for (DsmGuiModelChangeListener listener : listeners)
listener.dsmGuiModelChanged();
}
// TODO efficiency problems with this
private void fireDsmDataChanged() {
for (DsmGuiModelChangeListener listener : listeners)
listener.dsmDataChanged();
}
public void addChangeListener(DsmGuiModelChangeListener listener) {
listeners.add(listener);
}
public void clearSelection() {
selectCells(Collections.EMPTY_LIST, Collections.EMPTY_LIST);
}
public void setDsm(Dsm dsm, AnalysisResult analysisResult) {
this.analysisResult = analysisResult;
clearSelection();
cellInfoCache.clear();
this.dsm = dsm;
displayNameFormatter = null;
fireDsmDataChanged();
}
public Set<Dependency> getSelectionDependencies() {
Set<Dependency> result = new HashSet();
for (Integer col : selectedCols)
for (Integer row : selectedRows)
result.add(getDsmCell(row, col).getDependency());
return result;
}
public Set<Dependable> getSelectionDependables() {
if (selectedRows.isEmpty())
return Collections.EMPTY_SET;
Set<Dependency> selectionDependencies = getSelectionDependencies();
Set<Dependable> result = new HashSet();
if (selectionDependencies.isEmpty()) {
for (int row : selectedRows)
result.add(dsm.getRows().get(row).getDependee());
} else {
for (Dependency dependency : selectionDependencies) {
result.add(dependency.getDependant());
result.add(dependency.getDependee());
}
}
return result;
}
public boolean isSelected(int row, int col) {
return selectedRows.contains(row) && selectedCols.contains(col);
}
public void setDisplayNameFormat(DisplayNameFormat nameFormat) {
if (nameFormat.equals(this.displayNameFormat))
return;
displayNameFormat = nameFormat;
displayNameFormatter = null;
fireDsmGuiModelChanged();
}
private Formatter getDisplayNameFormatter() {
if (displayNameFormatter == null) {
if (displayNameFormat.equals(DisplayNameFormat.shortened))
displayNameFormatter = new ShortenedNameFormatter(getRowNames());
else
displayNameFormatter = new PassThroughFormatter();
}
return displayNameFormatter;
}
private List<String> getRowNames() {
List<String> names = new ArrayList();
for (DsmRow row : dsm.getRows())
names.add(row.getDependee().getDisplayName());
return names;
}
public DisplayNameFormat getDisplayNameFormat() {
return displayNameFormat;
}
}