blob: 8307d2d3424c57f5a0b63df72363f3af91cb8706 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Angelo Zerr 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:
* Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.ui.css.core.dom.properties.providers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.e4.ui.css.core.dom.CSSStylableElement;
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.core.exceptions.UnsupportedClassCSSPropertyException;
import org.eclipse.e4.ui.css.core.utils.StringUtils;
import org.w3c.dom.css.CSSStyleDeclaration;
/**
* CSS property handler with lazy strategy. {@link ICSSPropertyHandler} are
* retrieved with name into packages registered with registerPackage method.
*/
public class CSSPropertyHandlerLazyProviderImpl extends
AbstractCSSPropertyHandlerProvider {
private static Log logger = LogFactory
.getLog(CSSPropertyHandlerLazyProviderImpl.class);
// List of package names containing handlers class for properties
private List packageNames = new ArrayList();
// Map used as a cache for properties handlers found
private Map propertyToHandlersMap = new HashMap();
/**
* Return the list of PropertiesHandler corresponding to the property name
* given as argument
*/
public Collection getCSSPropertyHandlers(String property) throws Exception {
// Test if ICSSPropertyHandler List was stored into cache
// with key property
Map propertyHandlers = getPropertyToHandlersMap();
Object h = propertyHandlers.get(property);
if (h != null) {
// Test if there
if (h instanceof List)
return (List) h;
return null;
}
List handlers = null;
try {
String handlerClassName = getHandlerClassName(property);
for (Iterator iterator = packageNames.iterator(); iterator
.hasNext();) {
String packageName = (String) iterator.next();
ICSSPropertyHandler handler = getCSSPropertyHandler(
packageName, handlerClassName);
if (handler != null) {
if (logger.isDebugEnabled())
logger.debug("Handle CSS Property=" + property
+ ", with class=" + packageName + "."
+ handlerClassName);
if (handlers == null)
handlers = new ArrayList();
handlers.add(handler);
}
}
if (logger.isDebugEnabled()) {
if (handlers == null)
logger.debug("Cannot find Handle Class CSS Property="
+ property + ", for class=" + handlerClassName);
}
} finally {
if (handlers != null)
propertyHandlers.put(property, handlers);
else
propertyHandlers.put(property, "__HANDLER_NOT_FOUND__");
}
return handlers;
}
/**
* Register a package path "name.name1." where to search for PropertyHandler
* class
*
* @param packageName
*/
public void registerPackage(String packageName) {
packageNames.add(packageName);
propertyToHandlersMap = null;
}
protected Map getPropertyToHandlersMap() {
if (propertyToHandlersMap == null)
propertyToHandlersMap = new HashMap();
return propertyToHandlersMap;
}
/**
* Reflexive method that return a property handler class
*
* @param packageName
* @param handlerClassName
* @return
* @throws Exception
*/
protected ICSSPropertyHandler getCSSPropertyHandler(String packageName,
String handlerClassName) throws Exception {
String handlerClass = packageName + "." + handlerClassName;
try {
Class clazz = this.getClass().getClassLoader().loadClass(
handlerClass);
Object instance = clazz.newInstance();
if (!(instance instanceof ICSSPropertyHandler)) {
throw new UnsupportedClassCSSPropertyException(clazz);
}
return (ICSSPropertyHandler) clazz.newInstance();
} catch (ClassNotFoundException e) {
}
return null;
}
/**
* Return the handler class name corresponding to the property label given
* as argument A Property Handler Class Name is CSSPropertyXXXHandler (like
* CSSPropertyBorderTopColorHandler)
*
* @param property
* @return
*/
protected String getHandlerClassName(String property) {
String handlerClassName = "CSSProperty";
String[] s = StringUtils.split(property, "-");
for (int i = 0; i < s.length; i++) {
String p = s[i];
p = p.substring(0, 1).toUpperCase() + p.substring(1, p.length());
handlerClassName += p;
}
handlerClassName += "Handler";
return handlerClassName;
}
/*
* (non-Javadoc)
* @see org.eclipse.e4.ui.css.core.dom.properties.providers.AbstractCSSPropertyHandlerProvider#getDefaultCSSStyleDeclaration(org.eclipse.e4.ui.css.core.engine.CSSEngine,
* org.eclipse.e4.ui.css.core.dom.CSSStylableElement,
* org.w3c.dom.css.CSSStyleDeclaration)
*/
protected CSSStyleDeclaration getDefaultCSSStyleDeclaration(
CSSEngine engine, CSSStylableElement stylableElement,
CSSStyleDeclaration newStyle, String pseudoE) throws Exception {
if (stylableElement.getDefaultStyleDeclaration(pseudoE) != null)
return stylableElement.getDefaultStyleDeclaration(pseudoE);
if (newStyle != null) {
StringBuffer style = null;
int length = newStyle.getLength();
for (int i = 0; i < length; i++) {
String propertyName = newStyle.item(i);
String[] compositePropertiesNames = engine
.getCSSCompositePropertiesNames(propertyName);
if (compositePropertiesNames != null) {
for (int j = 0; j < compositePropertiesNames.length; j++) {
propertyName = compositePropertiesNames[j];
String s = getCSSPropertyStyle(engine, stylableElement,
propertyName, pseudoE);
if (s != null) {
if (style == null)
style = new StringBuffer();
style.append(s);
}
}
} else {
String s = getCSSPropertyStyle(engine, stylableElement,
propertyName, pseudoE);
if (s != null) {
if (style == null)
style = new StringBuffer();
style.append(s);
}
}
}
if (style != null) {
CSSStyleDeclaration defaultStyleDeclaration = engine
.parseStyleDeclaration(style.toString());
stylableElement.setDefaultStyleDeclaration(pseudoE,
defaultStyleDeclaration);
return defaultStyleDeclaration;
}
}
return stylableElement.getDefaultStyleDeclaration(pseudoE);
}
}