blob: 0fe893f568cf914e5d459e19bfa5ecff676eb783 [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.resources.css;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.css.ast.Context;
import com.google.gwt.resources.css.ast.CssCompilerException;
import com.google.gwt.resources.css.ast.CssDef;
import com.google.gwt.resources.css.ast.CssProperty;
import com.google.gwt.resources.css.ast.CssProperty.DotPathValue;
import com.google.gwt.resources.css.ast.CssProperty.ExpressionValue;
import com.google.gwt.resources.css.ast.CssProperty.FunctionValue;
import com.google.gwt.resources.css.ast.CssProperty.IdentValue;
import com.google.gwt.resources.css.ast.CssProperty.ListValue;
import com.google.gwt.resources.css.ast.CssProperty.Value;
import com.google.gwt.resources.css.ast.CssUrl;
import com.google.gwt.resources.css.ast.CssVisitor;
import com.google.gwt.resources.ext.ResourceContext;
import com.google.gwt.resources.ext.ResourceGeneratorUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Substitute symbolic replacements into string values.
*/
public class SubstitutionReplacer extends CssVisitor {
private final ResourceContext context;
private final JClassType dataResourceType;
private final JClassType imageResourceType;
private final TreeLogger logger;
private final Map<String, CssDef> substitutions;
public SubstitutionReplacer(TreeLogger logger, ResourceContext context,
Map<String, CssDef> substitutions) {
this.context = context;
this.dataResourceType = context.getGeneratorContext().getTypeOracle().findType(
DataResource.class.getCanonicalName());
this.imageResourceType = context.getGeneratorContext().getTypeOracle().findType(
ImageResource.class.getCanonicalName());
this.logger = logger;
this.substitutions = substitutions;
}
@Override
public void endVisit(CssProperty x, Context ctx) {
if (x.getValues() == null) {
// Nothing to do
return;
}
x.setValue(substituteDefs(x.getValues()));
}
private ListValue substituteDefs(ListValue listValue) {
List<Value> result = new ArrayList<Value>(listValue.getValues().size());
for (Value val : listValue.getValues()) {
if (val.isFunctionValue() != null) {
// Recursively perform substitution on a function's values
FunctionValue fnVal = val.isFunctionValue();
ListValue newVals = substituteDefs(fnVal.getValues());
result.add(new FunctionValue(fnVal.getName(), newVals));
continue;
}
IdentValue maybeIdent = val.isIdentValue();
if (maybeIdent == null) {
// Not an ident, append as-is to result
result.add(val);
continue;
}
String identStr = maybeIdent.getIdent();
CssDef def = substitutions.get(identStr);
if (def == null) {
// No substitution found, append as-is to result
result.add(val);
continue;
} else if (def instanceof CssUrl) {
assert def.getValues().size() == 1;
assert def.getValues().get(0).isDotPathValue() != null;
DotPathValue functionName = def.getValues().get(0).isDotPathValue();
JType methodType = null;
try {
methodType = ResourceGeneratorUtil.getMethodByPath(context.getClientBundleType(),
functionName.getParts(), null).getReturnType();
} catch (NotFoundException e) {
logger.log(TreeLogger.ERROR, e.getMessage());
throw new CssCompilerException("Cannot find data method");
}
if (!methodType.equals(dataResourceType) &&
!methodType.equals(imageResourceType)) {
String message = "Invalid method type for url substitution: " + methodType + ". " +
"Only DataResource and ImageResource are supported.";
logger.log(TreeLogger.ERROR, message);
throw new CssCompilerException(message);
}
String instance = "((" + methodType.getQualifiedSourceName() + ")("
+ context.getImplementationSimpleSourceName() + ".this."
+ functionName.getExpression() + "))";
StringBuilder expression = new StringBuilder();
expression.append("\"url('\" + ");
if (methodType.equals(dataResourceType)) {
expression.append(instance).append(".getUrl()");
} else if (methodType.equals(imageResourceType)) {
expression.append(instance).append(".getURL()");
}
expression.append(" + \"')\"");
result.add(new ExpressionValue(expression.toString()));
} else {
for (Value defValue : def.getValues()) {
result.add(defValue);
}
}
}
return new ListValue(result);
}
}