/*******************************************************************************
* Copyright (c) 2016 ARM Ltd. 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:
* ARM Ltd and ARM Germany GmbH - Initial API and implementation
*******************************************************************************/
package com.arm.cmsis.pack.installer.ui;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.ui.IWorkbenchPart;
import com.arm.cmsis.pack.CpPlugIn;
import com.arm.cmsis.pack.ICpPackManager;
import com.arm.cmsis.pack.common.CmsisConstants;
import com.arm.cmsis.pack.data.ICpBoard;
import com.arm.cmsis.pack.data.ICpExample;
import com.arm.cmsis.pack.data.ICpItem;
import com.arm.cmsis.pack.data.ICpPack;
import com.arm.cmsis.pack.data.ICpPack.PackState;
import com.arm.cmsis.pack.data.ICpPackCollection;
import com.arm.cmsis.pack.installer.ui.views.BoardsView;
import com.arm.cmsis.pack.installer.ui.views.DevicesView;
import com.arm.cmsis.pack.data.ICpPackFamily;
import com.arm.cmsis.pack.item.ICmsisItem;
import com.arm.cmsis.pack.rte.boards.IRteBoardDeviceItem;
import com.arm.cmsis.pack.rte.devices.IRteDeviceItem;
import com.arm.cmsis.pack.rte.examples.IRteExampleItem;
import com.arm.cmsis.pack.utils.Utils;
/**
* The filter used to filter the packs and examples
*/
public class PackInstallerViewFilter extends ViewerFilter {
protected IRteDeviceItem fDeviceItem = null ;
protected IRteBoardDeviceItem fBoardItem = null;
protected boolean bAllDevices = false;
protected boolean bAllBoards = false;
protected String fBoardName = null;
protected Set<String> fSelectedDeviceNames = null;
protected IWorkbenchPart selectionPart;
protected IStructuredSelection selection;
protected boolean installedOnly;
protected String filterString = null;
protected Set<ICpPackFamily> fFilteredDevicePackFamilies = new HashSet<ICpPackFamily>();
/**
* Default constructor
*/
public PackInstallerViewFilter() {
installedOnly = false;
}
public void clear() {
selection = null;
selectionPart = null;
fFilteredDevicePackFamilies.clear();
fSelectedDeviceNames = null;
fDeviceItem = null;
fBoardItem = null;
filterString = null;
}
public Set<ICpPackFamily> getFilteredDevicePackFamilies() {
return fFilteredDevicePackFamilies;
}
/**
* @param part
* @param selection
*/
public boolean setSelection(IWorkbenchPart part, IStructuredSelection selection) {
this.selectionPart = part;
this.selection = selection;
boolean bFilterChanged = updateFilter();
if(bFilterChanged) {
updateFilterdPacks();
}
return bFilterChanged;
}
protected void updateFilterdPacks() {
fFilteredDevicePackFamilies.clear();
ICpPackManager pm = CpPlugIn.getPackManager();
ICpPackCollection dfps = pm.getDevicePacks();
if(dfps == null || !dfps.hasChildren())
return;
for(ICpItem item : dfps.getChildren()) {
if(item instanceof ICpPackFamily) {
ICpPackFamily f = (ICpPackFamily) item;
if(isDevicePackFamilyFiltered(f))
fFilteredDevicePackFamilies.add(f);
}
}
}
protected boolean updateFilter() {
filterString = createFilterString();
if (selectionPart instanceof DevicesView) {
return setDeviceSelection();
} else if (selectionPart instanceof BoardsView) {
return setBoardSelection();
}
return false;
}
protected boolean setDeviceSelection() {
IRteDeviceItem item = null;
if(selection != null && selection.size() == 1) {
item = (IRteDeviceItem) selection.getFirstElement();
bAllDevices = CmsisConstants.ALL_DEVICES.equals(item.getName());
} else {
bAllDevices = false;
}
return setDeviceItem(item);
}
protected boolean setDeviceItem(IRteDeviceItem item) {
if(fDeviceItem == item)
return false;
fBoardItem = null;
fBoardName = null;
fDeviceItem = item;
if(fDeviceItem != null && !bAllDevices) {
fSelectedDeviceNames = item.getAllDeviceNames();
} else {
fSelectedDeviceNames = null;
}
return true;
}
protected boolean setBoardSelection() {
ICmsisItem item = null;
if(selection != null && selection.size() == 1) {
item = (ICmsisItem) selection.getFirstElement();
bAllBoards = CmsisConstants.ALL_BOARDS.equals(item.getName());
} else {
bAllBoards = false;
}
if(item != null && item instanceof IRteDeviceItem)
return setDeviceItem((IRteDeviceItem)item);
return setBoardItem((IRteBoardDeviceItem)item);
}
protected boolean setBoardItem(IRteBoardDeviceItem item) {
if(fBoardItem == item)
return false;
fBoardItem = item;
fDeviceItem = null;
if(fBoardItem != null && !bAllBoards ) {
fBoardName = fBoardItem.getName();
fSelectedDeviceNames = fBoardItem.getAllDeviceNames();
} else {
fBoardName = null;
fSelectedDeviceNames = null;
}
return true;
}
public String getFilterString() {
return filterString;
}
protected String createFilterString() {
if (selection == null || selection.isEmpty()) {
if (selectionPart instanceof DevicesView) {
return Messages.PacksExamplesViewFilter_NoDevices;
} else if (selectionPart instanceof BoardsView) {
return Messages.PacksExamplesViewFilter_NoBoards;
} else {
return null;
}
}
ICmsisItem item = (ICmsisItem) selection.getFirstElement();
if (item != null) {
if (selectionPart instanceof BoardsView &&
(CmsisConstants.MOUNTED_DEVICES.equals(item.getName()) ||
CmsisConstants.COMPATIBLE_DEVICES.equals(item.getName()))) {
return item.getChildren().iterator().next().getName()
+ " (" + item.getName() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
}
return item.getName();
}
return null;
}
/**
* Set to filter out uninstalled examples
* @param installedOnly
*/
public void setInstalledOnly(boolean installedOnly) {
this.installedOnly = installedOnly;
}
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IRteExampleItem) {
return selectExamples((IRteExampleItem) element);
} else if (element instanceof ICpPackFamily)
return selectPacks( (ICpPackFamily) element);
return true;
}
protected boolean isDevicePackFamilyFiltered(ICpPackFamily f) {
ICpPack pack = f.getPack();
if (pack == null) {
return false;
}
if(pack.isDevicelessPack()) {
return false;
}
if(fDeviceItem != null) {
if(bAllDevices)
return true;
if(fSelectedDeviceNames == null)
return false;
return packContainsRteDevice(fDeviceItem, pack);
} else if (fBoardItem != null) {
if(bAllBoards)
return true;
if(fSelectedDeviceNames == null)
return false;
if(fBoardName == null)
return false;
return packContainsBoard(fBoardItem, pack);
}
return false;
}
protected boolean selectPacks(ICpPackFamily f) {
ICpPack pack = f.getPack();
if (pack == null) {
return false;
}
if(pack.isDevicelessPack()) {
return true;
}
return fFilteredDevicePackFamilies.contains(f);
}
/**
* @param board The board
* @param pack The pack
* @return true if pack contains this board, otherwise false
*/
private boolean packContainsBoard(IRteBoardDeviceItem board, ICpPack pack) {
// check if the pack contains a board
Set<String> boardNames = pack.getBoardNames();
if(boardNames != null && boardNames.contains(fBoardName))
return true;
Set<String> devicesContainedInPack = pack.getAllDeviceNames();
if (Utils.checkIfIntersect(fSelectedDeviceNames, devicesContainedInPack)) {
return true;
}
IRteDeviceItem mountedDevices = board.getMountedDevices();
IRteDeviceItem compatibleDevices = board.getCompatibleDevices();
return packContainsRteDevice(mountedDevices, pack) ||
packContainsRteDevice(compatibleDevices, pack);
}
/**
* Convert the ICpItem to IRteDeviceItem
* @param item
* @return the corresponding IRteDeviceItem, null if no matching IRteDeviceItem is found
*/
private IRteDeviceItem convertCpItemToRteDeviceItem(ICpItem item) {
String vendorName = item.getVendor();
String deviceName = CmsisConstants.EMPTY_STRING;
if (item.hasAttribute(CmsisConstants.DFAMILY)) {
deviceName = item.getAttribute(CmsisConstants.DFAMILY);
} else if (item.hasAttribute(CmsisConstants.DSUBFAMILY)) {
deviceName = item.getAttribute(CmsisConstants.DSUBFAMILY);
} else if (item.hasAttribute(CmsisConstants.DNAME)) {
deviceName = item.getAttribute(CmsisConstants.DNAME);
} else if (item.hasAttribute(CmsisConstants.DVARIANT)) {
deviceName = item.getAttribute(CmsisConstants.DVARIANT);
}
if (vendorName.isEmpty()) {
return null;
}
IRteDeviceItem allRteDevices = CpPlugIn.getPackManager().getDevices();
if (deviceName.isEmpty()) {
return allRteDevices.getVendorItem(vendorName);
}
return allRteDevices.findItem(deviceName, vendorName, false);
}
private boolean packContainsRteDevice(IRteDeviceItem deviceItem, ICpPack pack) {
if (deviceItem == null) {
return false;
}
if(deviceItem == fDeviceItem) {
Set<String> devicesContainedInPack = pack.getAllDeviceNames();
if (Utils.checkIfIntersect(fSelectedDeviceNames, devicesContainedInPack)) {
return true;
}
}
// Check if the mounted devices or compatible devices on this pack's board
// intersect with deviceItem's devices
Collection<? extends ICpItem> boards = pack.getGrandChildren(CmsisConstants.BOARDS_TAG);
if (boards == null || boards.isEmpty()) {
return false;
}
for (ICpItem item : boards) {
if(!(item instanceof ICpBoard)) {
continue;
}
ICpBoard b = (ICpBoard)item;
Collection<ICpItem> mountedDevices = b.getMountedDevices();
for (ICpItem mountedDevice : mountedDevices) {
IRteDeviceItem mountedDeviceItemInPack = convertCpItemToRteDeviceItem(mountedDevice);
if (mountedDeviceItemInPack == null) {
continue;
}
Set<String> temp = mountedDeviceItemInPack.getAllDeviceNames();
if (Utils.checkIfIntersect(temp, fSelectedDeviceNames)) {
return true;
}
}
Collection<ICpItem> compatibleDevices = b.getCompatibleDevices();
for (ICpItem compatibleDevice : compatibleDevices) {
// Check intersection
IRteDeviceItem compatibleDeviceItemInPack = convertCpItemToRteDeviceItem(compatibleDevice);
if (compatibleDeviceItemInPack == null) {
continue;
}
// Check intersection
Set<String> temp = compatibleDeviceItemInPack.getAllDeviceNames();
if (Utils.checkIfIntersect(temp, fSelectedDeviceNames)) {
return true;
}
}
}
return false;
}
private boolean selectExamples(IRteExampleItem exampleItem ) {
if (exampleItem == null) {
return false;
}
ICpExample example = exampleItem.getExample();
if (example == null)
return false;
if(fDeviceItem == null && fBoardItem == null)
return false;
if(installedOnly &&
example.getPack().getPackState() != PackState.INSTALLED &&
example.getPack().getPackState() != PackState.GENERATED) {
return false;
}
if (fDeviceItem != null) {
if (bAllDevices) {
return true;
}
return boardContainsDevice(example.getBoard(), fDeviceItem);
} else if (fBoardItem != null) {
if (bAllBoards) {
return true;
}
return exampleContainsBoard(example, fBoardItem.getBoard());
}
return false;
}
private boolean exampleContainsBoard(ICpExample example, ICpBoard board) {
if (example.getBoard() != null && board != null) {
return example.getBoard().getId().equals(board.getId());
}
return false;
}
private boolean boardContainsDevice(ICpBoard b, IRteDeviceItem rteDeviceItem) {
if (b == null) {
return false;
}
IRteBoardDeviceItem board = CpPlugIn.getPackManager().getRteBoardDevices().findBoard(b.getId());
if (board != null) {
if (Utils.checkIfIntersect(board.getAllDeviceNames(), fSelectedDeviceNames)) {
return true;
}
}
return false;
}
}