blob: db64c7c9c1265955e205c0177e000f7162f35a32 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.internal.workspace;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.scout.commons.CompareUtility;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.commons.WeakEventListener;
import org.eclipse.scout.sdk.ScoutFileLocator;
import org.eclipse.scout.sdk.extensions.runtime.bundles.RuntimeBundles;
import org.eclipse.scout.sdk.extensions.runtime.classes.IRuntimeClasses;
import org.eclipse.scout.sdk.icon.IIconProvider;
import org.eclipse.scout.sdk.icon.ScoutIconDesc;
import org.eclipse.scout.sdk.internal.ScoutSdk;
import org.eclipse.scout.sdk.util.type.TypeUtility;
import org.eclipse.scout.sdk.util.typecache.ICachedTypeHierarchy;
import org.eclipse.scout.sdk.util.typecache.ITypeHierarchyChangedListener;
import org.eclipse.scout.sdk.workspace.IScoutBundle;
import org.eclipse.scout.sdk.workspace.IScoutBundleFilter;
import org.eclipse.scout.sdk.workspace.ScoutBundleFilters;
import org.eclipse.scout.sdk.workspace.type.ScoutTypeFilters;
import org.eclipse.scout.sdk.workspace.type.ScoutTypeUtility;
import org.eclipse.swt.graphics.ImageData;
public class ScoutProjectIcons implements IIconProvider {
private static final String[] PREDEFINED_EXTENSIONS = new String[]{"png", "ico", "gif"};
private static final String[] PREDEFINED_SUB_FOLDERS = new String[]{"resources/icons/internal/", "resources/icons/"};
private final IScoutBundle m_bundle;
private P_Listener m_listener;
private Map<String, ScoutIconDesc> m_cachedIcons;
private List<String> m_baseUrls;
public ScoutProjectIcons(IScoutBundle bundle) {
m_bundle = bundle;
}
@Override
public ScoutIconDesc[] getIcons() {
cache();
return m_cachedIcons.values().toArray(new ScoutIconDesc[m_cachedIcons.size()]);
}
@Override
public ScoutIconDesc getIcon(String key) {
cache();
return m_cachedIcons.get(key);
}
// internal cache methods
private void clearCache() {
m_cachedIcons = null;
}
protected synchronized void cache() {
if (m_cachedIcons == null) {
m_baseUrls = buildBaseUrls();
Map<String, ScoutIconDesc> collector = new HashMap<String, ScoutIconDesc>();
collectIconNames(collector);
for (ScoutIconDesc desc : collector.values()) {
findIconInProject(desc);
}
m_cachedIcons = new HashMap<String, ScoutIconDesc>(collector);
}
}
private List<String> buildBaseUrls() {
Set<? extends IScoutBundle> childBundles = m_bundle.getChildBundles(new IScoutBundleFilter() {
@Override
public boolean accept(IScoutBundle bundle) {
return isInterestingBundleType(bundle.getType());
}
}, true);
List<String> types = RuntimeBundles.getTypes();
ArrayList<String> bundles = new ArrayList<String>(childBundles.size() + types.size());
// Project bundles
for (IScoutBundle parentBundle : childBundles) {
bundles.add(parentBundle.getSymbolicName());
}
// Scout RT Bundles
for (String s : types) {
if (isInterestingBundleType(s)) {
String bundleSymbolicName = RuntimeBundles.getBundleSymbolicName(s);
if (StringUtility.hasText(bundleSymbolicName)) {
bundles.add(bundleSymbolicName);
}
}
}
bundles.trimToSize();
return bundles;
}
protected boolean isInterestingBundleType(String type) {
return StringUtility.hasText(type) && (type.contains(IScoutBundle.TYPE_CLIENT) || type.contains("UI_")) && !type.contains("TESTING");
}
protected void collectIconNames(Map<String, ScoutIconDesc> collector) {
IType abstractIcons = TypeUtility.getType(IRuntimeClasses.AbstractIcons);
if (!TypeUtility.exists(abstractIcons)) {
return;
}
ICachedTypeHierarchy iconsHierarchy = TypeUtility.getPrimaryTypeHierarchy(abstractIcons);
if (m_listener == null) {
m_listener = new P_Listener();
iconsHierarchy.addHierarchyListener(m_listener);
}
Set<? extends IScoutBundle> parentSharedBundles = m_bundle.getParentBundles(ScoutBundleFilters.getBundlesOfTypeFilter(IScoutBundle.TYPE_SHARED), true);
for (IScoutBundle parentShared : parentSharedBundles) {
for (IType iconType : iconsHierarchy.getAllSubtypes(abstractIcons, ScoutTypeFilters.getInScoutBundles(parentShared))) {
if (TypeUtility.exists(iconType)) {
try {
collectIconNamesOfType(iconType, iconsHierarchy, collector);
}
catch (Exception e) {
ScoutSdk.logWarning("Unable to collect icon names for class '" + iconType.getFullyQualifiedName() + "'.", e);
}
}
}
}
}
protected void collectIconNamesOfType(IType iconType, ICachedTypeHierarchy iconsHierarchy, Map<String, ScoutIconDesc> collector) throws JavaModelException {
if (TypeUtility.exists(iconType)) {
boolean inherited = CompareUtility.notEquals(ScoutTypeUtility.getScoutBundle(iconType), m_bundle);
for (IField field : iconType.getFields()) {
if (Flags.isPublic(field.getFlags()) && field.getSource() != null && field.getSource().contains(" String ")) {
Object fieldConstant = TypeUtility.getFieldConstant(field);
if (fieldConstant instanceof String) {
String iconName = fieldConstant.toString();
collector.put(iconName, new ScoutIconDesc(field.getElementName(), iconName, field, inherited));
}
}
}
collectIconNamesOfType(iconsHierarchy.getSuperclass(iconType), iconsHierarchy, collector);
}
}
@SuppressWarnings("resource")
protected void findIconInProject(ScoutIconDesc desc) {
if (desc == null || !StringUtility.hasText(desc.getIconName())) {
return;
}
for (String baseUrl : m_baseUrls) {
for (String ext : PREDEFINED_EXTENSIONS) {
for (String folder : PREDEFINED_SUB_FOLDERS) {
String imgPath = folder + desc.getIconName() + "." + ext;
InputStream is = null;
try {
is = ScoutFileLocator.resolve(baseUrl, imgPath);
if (is != null) {
ImageDescriptor desc1 = ImageDescriptor.createFromImageData(new ImageData(is));
if (desc1 != null) {
desc.setImgDesc(desc1);
return;
}
}
}
finally {
if (is != null) {
try {
is.close();
}
catch (IOException e) {
ScoutSdk.logWarning("could not close input stream of file '" + baseUrl + "" + imgPath + "'.", e);
}
}
}
}
}
}
}
private class P_Listener implements ITypeHierarchyChangedListener, WeakEventListener {
@Override
public void hierarchyInvalidated() {
clearCache();
}
}
}