/******************************************************************************* * Copyright (c) 2015 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.item; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import com.arm.cmsis.pack.common.CmsisConstants; import com.arm.cmsis.pack.utils.WildCards; /** * Generic tree of Cmsis items */ public class CmsisTreeItem<T extends ICmsisTreeItem<T>> extends CmsisItem implements ICmsisTreeItem<T> { protected T fParent = null; protected String fName = null; protected Collection<T> fChildren = null; /** * Default constructor */ public CmsisTreeItem() { } /** * Hierarchical constructor * @param parent parent item in the hierarchy */ public CmsisTreeItem(T parent) { fParent = parent; } /** * Hierarchical constructor * @param parent parent item in the hierarchy * @param name item name */ public CmsisTreeItem(T parent, String name) { fParent = parent; fName = name; } @Override public void clear() { super.clear(); fChildren = null; } @Override public void destroy() { super.destroy(); fParent = null; fName = null; } @Override public boolean purge() { Collection<? extends T> children = getChildren(); if(children == null) { return false; } for (Iterator<? extends T> iterator = children.iterator(); iterator.hasNext();) { T child = iterator.next(); if(child.purge()) { iterator.remove(); cachedChildArray = null; } } if(children.isEmpty()) { destroy(); return true; } return false; } @Override public void setParent(T parent) { if(fParent == parent) { return; } if(fParent != null) { fParent.removeChild(getThisItem()); } fParent = parent; } @Override public String getName() { if(fName == null) { fName = constructName(); if(fName == null && !fName.isEmpty()) { fName = super.getName(); } } return fName; } /** * Constructs item name * @return constructed item name */ protected String constructName() { return CmsisConstants.EMPTY_STRING; } @Override public T getParent() { return fParent; } @SuppressWarnings("unchecked") public T getThisItem() { return (T)this; // we know that this item type is T : T extends ICmsisTreeItem<T> } @Override public T getRoot() { if(fParent == null) { return getThisItem(); } return fParent.getRoot(); } @Override public Object[] getHierachyPath() { List<Object> segments = new LinkedList<Object>(); segments.add(this); for(T item = getParent(); item != null; item = item.getParent()){ if(item.getParent() != null) { segments.add(0, item); } } return segments.toArray(); } @Override public Collection<? extends T> getChildren() { return fChildren; } @Override public void addChild(T item) { if(item != null) { cachedChildArray = null; // invalidate children().add(item); } } /** * Returns child collection, creates one if not created yet * @return child */ protected Collection<T> children() { if(fChildren == null ) { fChildren = createCollection(); } return fChildren; } /** * Creates collection suitable to store child items. * Implementation can use List, Set or their descendants * @return created child collection */ protected Collection<T> createCollection(){ // default creates linkedList return new LinkedList<T>(); } @Override public boolean hasChildren() { Collection<? extends T> children = getChildren(); return children != null && !children.isEmpty(); } @Override public int getChildCount() { Collection<? extends T> children = getChildren(); if(children != null) { return children.size(); } return 0; } @Override public T getEffectiveItem() { return getThisItem(); } @Override public T getEffectiveParent() { return getParent(); } @Override public T getEffectiveHierarchyItem() { // default returns this item return getThisItem(); } @Override public Object[] getEffectiveHierachyPath() { List<Object> segments = new LinkedList<Object>(); for(T item = getEffectiveHierarchyItem(); item != null; item = item.getEffectiveParent()){ if(item.getParent() != null) { segments.add(0, item); } } return segments.toArray(); } @Override public Object[] getEffectiveChildArray() { return getEffectiveItem().getChildArray(); } @Override public Collection<? extends T> getEffectiveChildren() { return getEffectiveItem().getChildren(); } @Override public int getEffectiveChildCount() { Collection<? extends T> children = getEffectiveChildren(); if(children != null) { return children.size(); } return 0; } @Override public boolean hasEffectiveChildren() { Collection<? extends T> children = getEffectiveChildren(); return children != null && !children.isEmpty(); } @Override public String getItemKey(T item) { if(item == null) { return null; } return item.getName(); // default returns item name } @Override public T getFirstChild() { Collection<? extends T> children = getChildren(); if(children != null) { for(T child : children) { return child; } } return null; } @Override public String getFirstChildKey() { Collection<? extends T> children = getChildren(); if(children != null) { for(T child : children) { return getItemKey(child); } } return null; } @Override public T getFirstChild(String key) { if(key == null) { return null; } Collection<? extends T> children = getChildren(); if(children != null) { for(T child : children) { if(getItemKey(child).equals(key)) { return child; } } } return null; } @Override public String getFirstChildText(String key) { T item = getFirstChild(key); if(item != null) { return item.getText(); } return null; } @Override public void removeChild(T childToRemove) { Collection<? extends T> children = getChildren(); if(children == null) { return; } for (Iterator<? extends T> iterator = children.iterator(); iterator.hasNext();) { T child = iterator.next(); if(child.equals(childToRemove)) { iterator.remove(); cachedChildArray = null; } } } @Override public T removeFirstChild(String key) { if(key == null) { return null; } Collection<? extends T> children = getChildren(); if(children != null) { for(T child : children) { if(getItemKey(child).equals(key)) { children.remove(child); cachedChildArray = null; return child; } } } return null; } @Override public T removeAllChildren(String key) { if(key == null) { return null; } Collection<? extends T> children = getChildren(); if(children == null) { return null; } T firstRemovedChild = null; for (Iterator<? extends T> iterator = children.iterator(); iterator.hasNext();) { T child = iterator.next(); if(getItemKey(child).equals(key)) { if(firstRemovedChild == null) { firstRemovedChild = child; } iterator.remove(); cachedChildArray = null; } } return firstRemovedChild; } @Override public void replaceChild(T item) { if(item == null) { return; } if(item == this) { return; } removeAllChildren(getItemKey(item)); addChild(item); } @Override public T getFirstItem(String pattern) { if(WildCards.matchNoCase(pattern, getName())) { return getThisItem(); } Collection<? extends T> children = getChildren(); if(children == null) { return null; } for(T item : children) { T matchingItem = item.getFirstItem(pattern); if(matchingItem != null) { return matchingItem; } } return null; } }