/*******************************************************************************
* Copyright (c) 2013, 2014 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.ui.css.swt.properties.definition;
import static org.eclipse.e4.ui.css.swt.helpers.ThemeElementDefinitionHelper.normalizeId;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.WeakHashMap;
import org.eclipse.e4.ui.css.core.dom.properties.ICSSPropertyHandler;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.swt.dom.definition.ThemeDefinitionElement;
import org.eclipse.e4.ui.css.swt.helpers.URI;
import org.eclipse.e4.ui.internal.css.swt.CSSActivator;
import org.eclipse.e4.ui.internal.css.swt.definition.IThemeElementDefinitionOverridable;
import org.eclipse.osgi.service.localization.BundleLocalization;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.w3c.dom.css.CSSValue;
public class CSSPropertyThemeElementDefinitionHandler implements ICSSPropertyHandler {
private final static String CATEGORY_PROP = "category";
private final static String LABEL_PROP = "label";
private final static String DESCRIPTION_PROP = "description";
private final static String MESSAGE_QUERY_PARAM = "message";
private Map<Long, ResourceBundle> bundleToResourceBundles = new WeakHashMap<Long, ResourceBundle>();
@Override
public boolean applyCSSProperty(Object element, String property,
CSSValue value, String pseudo, CSSEngine engine) throws Exception {
if (!(element instanceof ThemeDefinitionElement<?>)) {
return false;
}
IThemeElementDefinitionOverridable<?> definition =
(IThemeElementDefinitionOverridable<?>) ((ThemeDefinitionElement<?>) element)
.getNativeWidget();
if (CATEGORY_PROP.equals(property)) {
definition.setCategoryId(normalizeId(value.getCssText().substring(1)));
} else if (LABEL_PROP.equals(property)) {
definition.setName(getLabel(value));
} else if (DESCRIPTION_PROP.equals(property)) {
definition.setDescription(getLabel(value));
}
return true;
}
@Override
public String retrieveCSSProperty(Object element, String property,
String pseudo, CSSEngine engine) throws Exception {
return null;
}
private String getLabel(CSSValue value) {
URL resourceBundleURL = getResourceBundleURL(value);
if (resourceBundleURL != null) {
String messageId = getMessageId(resourceBundleURL);
if (messageId != null) {
ResourceBundle resourceBundle = getResourceBundle(resourceBundleURL);
String message = resourceBundle != null ? resourceBundle.getString(messageId) : null;
if (message != null) {
return resourceBundle.getString(messageId);
}
}
}
return value.getCssText();
}
private String getMessageId(URL resourceBundleURL) {
String query = resourceBundleURL.getQuery();
if (query != null) {
int indexOfMessageParam = query.indexOf(MESSAGE_QUERY_PARAM);
if (indexOfMessageParam != -1) {
return query.substring(indexOfMessageParam + MESSAGE_QUERY_PARAM.length() + 1);
}
}
return null;
}
private Bundle getBundle(URI uri) throws BundleException {
Bundle bundle = CSSActivator.getDefault().getBundleForName(uri.lastSegment());
if (bundle != null && (bundle.getState() & Bundle.ACTIVE) == 0) {
bundle.start(); // Bundle is lazy init
}
return bundle;
}
private ResourceBundle getResourceBundle(URL resourceBundleURL) {
ResourceBundle resourceBundle = null;
try {
URI uri = URI.createURI(resourceBundleURL.getPath());
if (uri != null) {
resourceBundle = getResourceBundle(getBundle(uri));
}
} catch (Exception exc) {
// do nothing
}
return resourceBundle;
}
private ResourceBundle getResourceBundle(Bundle bundle) {
if (bundle == null) {
return null;
}
ResourceBundle resourceBundle = bundleToResourceBundles.get(bundle.getBundleId());
if (resourceBundle != null) {
return resourceBundle;
}
BundleLocalization localization = getBundleLocalization(bundle);
if (localization != null) {
resourceBundle = localization.getLocalization(bundle, null);
}
if (resourceBundle != null) {
bundleToResourceBundles.put(bundle.getBundleId(), resourceBundle);
}
return resourceBundle;
}
private BundleLocalization getBundleLocalization(Bundle bundle) {
ServiceReference<BundleLocalization> ref = bundle.getBundleContext().getServiceReference(
BundleLocalization.class);
return bundle.getBundleContext().getService(ref);
}
private URL getResourceBundleURL(CSSValue value) {
URL url = null;
if (hasResourceBundleUrl(value)) {
try {
url = new URL(((CSSPrimitiveValue) value).getStringValue());
} catch (MalformedURLException exc) {
// do nothing
}
}
return url;
}
private boolean hasResourceBundleUrl(CSSValue value) {
return value.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE
&& ((CSSPrimitiveValue) value).getPrimitiveType() == CSSPrimitiveValue.CSS_URI;
}
}