/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.generator;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Stack;
import java.util.TreeMap;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.DualHashBidiMap;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeSingleton;
import org.apache.velocity.tools.generic.AlternatorTool;
import org.apache.velocity.tools.generic.ComparisonDateTool;
import org.apache.velocity.tools.generic.ConversionTool;
import org.apache.velocity.tools.generic.DateTool;
import org.apache.velocity.tools.generic.DisplayTool;
import org.apache.velocity.tools.generic.EscapeTool;
import org.apache.velocity.tools.generic.RenderTool;
import org.apache.velocity.tools.generic.SortTool;
import org.openflexo.antar.binding.AbstractBinding.BindingEvaluationContext;
import org.openflexo.foundation.DataFlexoObserver;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.TargetType;
import org.openflexo.foundation.cg.CGFile;
import org.openflexo.foundation.cg.GenerationRepository;
import org.openflexo.foundation.cg.action.AbstractGCAction;
import org.openflexo.foundation.cg.generator.GeneratedCodeResult;
import org.openflexo.foundation.cg.generator.IFlexoResourceGenerator;
import org.openflexo.foundation.cg.templates.CGTemplate;
import org.openflexo.foundation.cg.templates.TemplateDeleted;
import org.openflexo.foundation.cg.templates.TemplateFileChanged;
import org.openflexo.foundation.cg.templates.TemplateFileEdited;
import org.openflexo.foundation.cg.templates.TemplateFileEditionCancelled;
import org.openflexo.foundation.cg.templates.TemplateFileRedefined;
import org.openflexo.foundation.cg.templates.TemplateFileSaved;
import org.openflexo.foundation.ontology.EditionPatternInstance;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.rm.GeneratedResourceData;
import org.openflexo.foundation.rm.ResourceType;
import org.openflexo.foundation.rm.cg.CGRepositoryFileResource;
import org.openflexo.generator.exception.GenerationException;
import org.openflexo.generator.exception.TemplateNotFoundException;
import org.openflexo.generator.exception.UnexpectedExceptionOccuredException;
import org.openflexo.generator.exception.VelocityException;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.logging.FlexoLogger;
import org.openflexo.toolbox.HTMLUtils;
import org.openflexo.toolbox.JavaUtils;
import org.openflexo.toolbox.StringUtils;
import org.openflexo.toolbox.ToolBox;
import org.openflexo.velocity.FlexoVelocity;
import org.openflexo.velocity.PostVelocityParser;
public abstract class Generator<T extends FlexoModelObject, R extends GenerationRepository> extends FlexoObservable implements
DataFlexoObserver {
private static final String VALID_XML_REGEXP = "[A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6"
+ "\\u00F8-\\u02ff\\u0370-\\u037d\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f"
+ "\\u2c00-\\u2fef\\u3001-\\udfff\\uf900-\\ufdcf\\ufdf0-\\ufffd\\-\\.0-9" + "\\u00b7\\u0300-\\u036f\\u203f-\\u2040]*";
private static final Pattern VALID_XML_PATTERN = Pattern.compile(VALID_XML_REGEXP);
private static final List<Class<?>> TOOL_CLASSES = Arrays.asList(AlternatorTool.class, ComparisonDateTool.class, ConversionTool.class,
DateTool.class, DisplayTool.class, EscapeTool.class, RenderTool.class, SortTool.class);
public static class Holder<T> {
private T value;
public T get() {
return value;
}
public T getValue() {
return get();
}
public void set(T value) {
this.value = value;
}
public void setValue(T value) {
set(value);
}
}
private static final Logger logger = FlexoLogger.getLogger(Generator.class.getPackage().getName());
private Vector<CGTemplate> _usedTemplates = new Vector<CGTemplate>();
private Vector<CGRepositoryFileResource<?, ?, ? extends CGFile>> generatedResources;
private Vector<CGRepositoryFileResource> concernedResources = null;
private T object;
protected AbstractProjectGenerator<R> projectGenerator;
private Date memoryLastGenerationDate;
private GenerationException generationException;
protected GeneratedCodeResult generatedCode;
private boolean isGenerating = false;
private boolean notifyObservers = true;
// This map is static because the velocity engine is static. To avoid this we should have 1 engine velocity per repository
private static Map<String, Long> macroLibMap = new HashMap<String, Long>(); // <Template Relative Path, Last modified date>
public Generator(AbstractProjectGenerator<R> projectGenerator, T object) {
this.projectGenerator = projectGenerator;
this.object = object;
this.generatedResources = new Vector<CGRepositoryFileResource<?, ?, ? extends CGFile>>();
if (projectGenerator != null) {
projectGenerator.addToGenerators(this);
}
}
@Override
public String getDeletedProperty() {
// TODO Auto-generated method stub
return null;
}
public AbstractProjectGenerator<R> getProjectGenerator() {
return projectGenerator;
}
public R getRepository() {
if (projectGenerator != null) {
return projectGenerator.getRepository();
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Project generator is not set.");
}
return null;
}
}
public final T getObject() {
return object;
}
public FlexoProject getProject() {
return getProjectGenerator().getProject();
}
public TargetType getTarget() {
return getProjectGenerator().getTarget();
}
public CGRepositoryFileResource resourceForKeyWithCGFile(ResourceType type, String resourceName) {
CGRepositoryFileResource ret = (CGRepositoryFileResource) getProject().resourceForKey(type, resourceName);
if (ret != null && ret.getCGFile() == null) {
ret.delete(false);
ret = null;
}
return ret;
}
public final String getPrefix() {
return getProject().getPrefix();
}
protected VelocityContext defaultContext() {
VelocityContext context = new VelocityContext();
if (object != null) {
context.put("object", object);
}
context.put("null", null);
context.put("project", getProject());
context.put("projectGenerator", getProjectGenerator());
context.put("repository", getRepository());
context.put("generator", this);
context.put("quote", "\"");
context.put("backslash", "\\");
context.put("sharp", "#");
context.put("dollar", "$");
context.put("prefix", getPrefix());
context.put("n", StringUtils.LINE_SEPARATOR);
context.put("trueValue", Boolean.TRUE);
context.put("falseValue", Boolean.FALSE);
context.put("toolbox", ToolBox.class);
context.put("javaUtils", JavaUtils.class);
context.put("Math", Math.class);
context.put("globalVariableMap", new HashMap<String, Object>());
context.put("today", new Date());
context.put("stringUtils", org.apache.commons.lang.StringUtils.class);
for (Class<?> klass : TOOL_CLASSES) {
try {
context.put(klass.getSimpleName(), klass.newInstance());
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return context;
}
/**
* Build or retrieve all resources (eventually just created) involved in this repository generation
*
* @param repository
* @return the list of resources (eventually just created) involved in this repository generation
*/
private Vector<CGRepositoryFileResource> buildGeneratedResourceListForRepository(R repository) {
Vector<CGRepositoryFileResource> returned = new Vector<CGRepositoryFileResource>();
buildResourcesAndSetGenerators(repository, returned);
return returned;
}
// public Vector<CGRepositoryFileResource> getConcernedResources(R repository)
// {
// if (concernedResources == null) {
// concernedResources = refreshConcernedResources();
// }
// return concernedResources;
// }
public Vector<CGRepositoryFileResource> refreshConcernedResources() {
return refreshConcernedResources(null);
}
public Vector<CGRepositoryFileResource> refreshConcernedResources(
Vector<CGRepositoryFileResource<? extends GeneratedResourceData, IFlexoResourceGenerator, CGFile>> forResources) {
Vector<CGRepositoryFileResource> oldConcernedResources = concernedResources;
concernedResources = buildGeneratedResourceListForRepository(getProjectGenerator().getRepository());
if (oldConcernedResources != null) {
for (CGRepositoryFileResource resource : oldConcernedResources) {
if (!concernedResources.contains(resource) && resource.getCGFile() != null) {
resource.getCGFile().setMarkedForDeletion(true);
}
}
}
for (CGRepositoryFileResource resource : concernedResources) {
resource.rebuildDependancies();
}
for (CGRepositoryFileResource resource : concernedResources) {
if (resource.needsGeneration() && (forResources == null || forResources.contains(resource))) {
resource.getDependantResourcesUpToDate();
}
}
return concernedResources;
}
public abstract void buildResourcesAndSetGenerators(R repository, Vector<CGRepositoryFileResource> resources);
/**
* Generate code related to this generator. If this generator may store result, setting forceGenerate flag to false will result in
* giving the already generated code (cache scheme).
*
* @param forceRegenerate
* @throws GenerationException
*/
public abstract void generate(boolean forceRegenerate) throws GenerationException;
/**
* Generate code related to this generator, using cache scheme if present Equivalent for call generate(false)
*
* @throws GenerationException
*/
public void generate() throws GenerationException {
generate(false);
}
public String merge(String templateName) throws GenerationException {
return merge(templateName, defaultContext());
}
private void updateVelocityMacroIfRequired() throws VelocityException, UnexpectedExceptionOccuredException {
try {
// the next lines ensures that the macro library will be added as a template used by this generator
List<CGTemplate> macroTemplates = getProjectGenerator().getVelocityMacroTemplates();
macroTemplates.addAll(getVelocityMacroTemplates());
synchronized (RuntimeSingleton.getRuntimeServices()) {
Map<String, Long> newMacroLibMap = new HashMap<String, Long>();
for (CGTemplate template : macroTemplates) {
newMacroLibMap.put(template.getRelativePath(), template.getLastUpdate().getTime());
notifyTemplateRequired(template);
}
if (!newMacroLibMap.equals(macroLibMap)) {
FlexoVelocity.addToVelocimacro(getTemplateLocator(), macroTemplates.toArray(new CGTemplate[0]));
macroLibMap = newMacroLibMap;
}
}
} catch (ResourceNotFoundException e) {
e.printStackTrace();
throw new VelocityException(e, getProjectGenerator());
} catch (ParseErrorException e) {
e.printStackTrace();
throw new VelocityException(e, getProjectGenerator());
} catch (Exception e) {
e.printStackTrace();
throw new UnexpectedExceptionOccuredException(e, getProjectGenerator());
}
}
/**
* Override this if you want to use one or more velocity macro library. <br>
* All macro templates from the project generator and from the current generator will be added for generation. Use the project generator
* one to include macros for all merge. <br>
* Order is important in case of multiple macro are defined with the same name. In such case, the last one will be taken into account.
*
* @return list of template to use as Macro library.
*/
public List<CGTemplate> getVelocityMacroTemplates() {
return new ArrayList<CGTemplate>();
}
public String merge(String templateRelativePath, VelocityContext velocityContext) throws GenerationException {
StringWriter sw = new StringWriter();
try {
updateVelocityMacroIfRequired();
CGTemplate template = templateWithName(templateRelativePath);
Velocity.setApplicationAttribute("templateLocator", getTemplateLocator());
FlexoVelocity.mergeTemplate(template.getRelativePathWithoutSetPrefix(), "UTF-8", velocityContext, sw);
Velocity.setApplicationAttribute("templateLocator", null);
} catch (TemplateNotFoundException e) {
throw e;
} catch (Throwable e) {
if (e instanceof MethodInvocationException) {
if (((MethodInvocationException) e).getWrappedThrowable() != null) {
((MethodInvocationException) e).getWrappedThrowable().printStackTrace();
}
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Could not merge template: " + e);
e.printStackTrace();
Throwable t = e;
while (t.getCause() != null) {
t = t.getCause();
}
if (!e.equals(t)) {
logger.fine("Originally caused by: " + t.getMessage());
t.printStackTrace();
}
}
throw new VelocityException(e, getProjectGenerator());
}
return PostVelocityParser.parseAndRenderCustomTag(sw.toString());
}
public AbstractGCAction getAction() {
return getProjectGenerator().getAction();
}
protected boolean hasProgressWindow() {
return getAction() != null && getAction().getFlexoProgress() != null;
}
protected void refreshProgressWindow(String stepName, boolean localize) {
if (hasProgressWindow()) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("************** refreshProgressWindow: " + stepName);
}
getAction().getFlexoProgress().setProgress(localize ? FlexoLocalization.localizedForKey(stepName) : stepName);
}
}
protected void resetSecondaryProgressWindow(int stepNb) {
if (hasProgressWindow()) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("**** resetSecondaryProgressWindow: " + stepNb);
}
getAction().getFlexoProgress().resetSecondaryProgress(stepNb);
}
}
protected void refreshSecondaryProgressWindow(String stepName, boolean localize) {
if (hasProgressWindow()) {
if (logger.isLoggable(Level.FINE)) {
logger.fine(">>>>>>>>>>>>> refreshSecondaryProgressWindow: " + stepName);
}
getAction().getFlexoProgress().setSecondaryProgress(localize ? FlexoLocalization.localizedForKey(stepName) : stepName);
}
}
public abstract Logger getGeneratorLogger();
public void addToGeneratedResourcesGeneratedByThisGenerator(CGRepositoryFileResource<?, ?, ? extends CGFile> resource) {
if (!generatedResources.contains(resource)) {
generatedResources.add(resource);
}
}
public void removeFromGeneratedResourcesGeneratedByThisGenerator(CGRepositoryFileResource<?, ?, ? extends CGFile> resource) {
generatedResources.remove(resource);
memoryLastGenerationDate = null;
generatedCode = null;
}
protected Vector<CGRepositoryFileResource<?, ?, ? extends CGFile>> getGeneratedResources() {
return generatedResources;
}
public TemplateLocator getTemplateLocator() {
return getProjectGenerator().getTemplateLocator();
}
public String getTemplatePath(String templateName) throws TemplateNotFoundException {
// Legacy method for backward compatibility
CGTemplate templateFile = getTemplateLocator().templateWithName(templateName);
notifyTemplateRequired(templateFile);
return templateName;
}
public CGTemplate templateWithName(String templateRelativePath) throws TemplateNotFoundException {
CGTemplate templateFile = getTemplateLocator().templateWithName(templateRelativePath);
notifyTemplateRequired(templateFile);
return templateFile;
}
public void clearTemplates() {
clearTemplates(false);
}
public void clearTemplates(boolean clearTemplateLocatorCache) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("clearTemplates() for " + this);
}
for (CGTemplate templateFile : _usedTemplates) {
templateFile.deleteObserver(this);
}
_usedTemplates.clear();
if (clearTemplateLocatorCache) {
getTemplateLocator().notifyTemplateModified();
}
}
public void notifyTemplateRequired(CGTemplate templateFile) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("notifyTemplateRequired " + templateFile.getRelativePath() + " for " + this);
}
if (!_usedTemplates.contains(templateFile)) {
_usedTemplates.add(templateFile);
templateFile.addObserver(this);
}
}
public void silentlyGenerateCode() {
notifyObservers = false;
try {
generate(true);
} catch (GenerationException e) {
e.printStackTrace();
}
notifyObservers = true;
}
public void startGeneration() {
isGenerating = true;
// getProjectGenerator().startGeneration(this);
if (needsRegenerationBecauseOfTemplateChange()) {
clearTemplates(true);
}
generationException = null;
}
public void stopGeneration() {
// getProjectGenerator().stopGeneration(this);
memoryLastGenerationDate = new Date();
isGenerating = false;
if (this instanceof IFlexoResourceGenerator && notifyObservers) {
setChanged();
notifyObservers(new ContentRegenerated(this, ((IFlexoResourceGenerator) this).getGeneratedCode()));
}
}
public Date getMemoryLastGenerationDate() {
if (memoryLastGenerationDate == null) {
if (generatedResources.size() == 0) {
memoryLastGenerationDate = new Date(1); // 1 because AFTER default template last update
} else {
for (CGRepositoryFileResource<?, ?, ? extends CGFile> r : generatedResources) {
Date d = r.getCGFile().getLastAcceptingDate();
if (d != null && (memoryLastGenerationDate == null || d.before(memoryLastGenerationDate))) {
memoryLastGenerationDate = d;
}
}
}
}
return memoryLastGenerationDate;
}
public boolean isCodeAlreadyGenerated() {
if (this instanceof IFlexoResourceGenerator) {
return ((IFlexoResourceGenerator) this).getGeneratedCode() != null;
}
// Not significant
return true;
}
/**
* @return
*/
public GeneratedCodeResult getGeneratedCode() {
return generatedCode;
}
public boolean needsGeneration() {
if (isGenerating) {
return false;
}
if (getGenerationException() != null) {
return true;
}
if (generatedResources.size() == 0) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("No resource generated by this generator!");
}
} else {
for (CGRepositoryFileResource<?, ?, ?> r : generatedResources) {
if (r.retrieveNeedsMemoryGenerationFlag()) {
return true;
}
}
}
return needsRegenerationBecauseOfTemplateUpdated() || needsRegenerationBecauseOfTemplateChange() || !isCodeAlreadyGenerated();
}
/**
* @return
*/
private boolean needsRegenerationBecauseOfTemplateChange() {
return getTemplateLocator() != null && getTemplateLocator().needsRegenerationBecauseOfTemplateChange(this);
}
public boolean needsRegenerationBecauseOfTemplateUpdated() {
return getTemplateLocator() != null && getTemplateLocator().needsUpdateForGenerator(getMemoryLastGenerationDate(), this);
}
public boolean needsRegenerationBecauseOfTemplateUpdated(Date diskLastGenerationDate) {
return getTemplateLocator() != null && getTemplateLocator().needsUpdateForGenerator(diskLastGenerationDate, this)
|| needsRegenerationBecauseOfTemplateChange();
}
public boolean hasFormattingException() {
return false;
}
public boolean hasAppendingException() {
return false;
}
public GenerationException getGenerationException() {
return generationException;
}
public void setGenerationException(GenerationException generationException) {
this.generationException = generationException;
if (projectGenerator != null) {
projectGenerator.notifyExceptionOccured(generationException);
}
stopGeneration();
}
protected void resetGenerationException() {
this.generationException = null;
}
@Override
public void update(FlexoObservable observable, DataModification dataModification) {
if (dataModification instanceof TemplateFileChanged || dataModification instanceof TemplateFileEditionCancelled
|| dataModification instanceof TemplateFileEdited || dataModification instanceof TemplateFileRedefined
|| dataModification instanceof TemplateFileSaved || dataModification instanceof TemplateDeleted) {
setChanged();
notifyObservers(dataModification);
}
}
/**
* Overrides getUsedTemplates
*
* @see org.openflexo.foundation.cg.generator.IFlexoResourceGenerator#getUsedTemplates()
*/
public Vector<CGTemplate> getUsedTemplates() {
return _usedTemplates;
}
public void setUsedTemplates(Vector<CGTemplate> templates) {
this._usedTemplates = templates;
}
public Holder<Object> getNewHolder() {
return new Holder<Object>();
}
public Vector<Object> getNewVector() {
return new Vector<Object>();
}
public List<Object> getNewList() {
return new ArrayList<Object>();
}
public Hashtable<Object, Object> getNewHashtable() {
return new Hashtable<Object, Object>();
}
public TreeMap<Object, Object> getNewTreeMap() {
return new TreeMap<Object, Object>();
}
public LinkedHashMap<Object, Object> getNewLinkedHashMap() {
return new LinkedHashMap<Object, Object>();
}
public Properties getNewProperties() {
return new Properties();
}
public TreeMap<FlexoModelObject, Object> getNewModelObjectTreeMap() {
return new TreeMap<FlexoModelObject, Object>(new FlexoModelObject.FlexoDefaultComparator<FlexoModelObject>());
}
public BidiMap getNewBidiMap() {
return new DualHashBidiMap();
}
public StringBuilder getNewStringBuilder() {
return new StringBuilder();
}
public Stack<Object> getNewStack() {
return new Stack<Object>();
}
public <C extends Comparable<C>> void sortVector(List<C> vectorToSort) {
Collections.sort(vectorToSort);
}
public void sortVectorOfModelObject(List<FlexoModelObject> vectorToSort) {
Collections.sort(vectorToSort, new FlexoModelObject.FlexoDefaultComparator<FlexoModelObject>());
}
public void sortEPIs(List<EditionPatternInstance> vectorToSort, final String binding) {
Collections.sort(vectorToSort, new Comparator<EditionPatternInstance>() {
@Override
public int compare(EditionPatternInstance o1, EditionPatternInstance o2) {
Object e1 = o1.evaluate(binding);
Object e2 = o2.evaluate(binding);
if (e1 == null) {
if (e2 == null) {
return 0;
} else {
return -1;
}
} else if (e2 == null) {
return 1;
}
if (e1 instanceof Comparable && e2 instanceof Comparable) {
try {
((Comparable) e1).compareTo(e2);
} catch (ClassCastException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not compare " + e1 + " with " + e2 + " Using string compare");
}
}
}
return e1.toString().compareTo(e2.toString());
}
});
}
public static String escapeStringForHTML(String s) {
return HTMLUtils.escapeStringForHTML(s, false);
}
public static String escapeStringForHTML(String s, boolean removeNewLine) {
return HTMLUtils.escapeStringForHTML(s, removeNewLine);
}
public static String extractBodyContent(String html) {
return HTMLUtils.extractBodyContent(html);
}
public static String extractBodyContent(String html, boolean returnHtmlIfNoBodyFound) {
return HTMLUtils.extractBodyContent(html, returnHtmlIfNoBodyFound);
}
public static String escapeStringForCsv(String s) {
return ToolBox.escapeStringForCsv(s);
}
public String capitalize(String s) {
return ToolBox.capitalize(s);
}
public static DateFormat getDateFormat(String pattern) {
return new SimpleDateFormat(pattern);
}
public static String escapeStringForJS(String s) {
return ToolBox.escapeStringForJS(s);
}
public static String escapeStringForProperties(String s) {
return ToolBox.escapeStringForProperties(s);
}
public static String removeAllWhiteCharacters(String text) {
return removeAllWhiteCharacters(text, " ");
}
public static String makeValidXMLName(String name) {
if (name == null) {
return name;
}
Matcher m = VALID_XML_PATTERN.matcher(name);
StringBuilder sb = new StringBuilder(name.length());
int lastMatch = 0;
while (m.find()) {
if (m.start() > lastMatch) {
for (int i = lastMatch; i < m.start(); i++) {
sb.append('_');
}
}
sb.append(m.group());
lastMatch = m.end();
}
if (lastMatch < name.length()) {
for (int i = lastMatch; i < name.length(); i++) {
sb.append('_');
}
}
return sb.toString();
}
public static String escapeStringForXML(String string) {
String escapedString = StringEscapeUtils.escapeXml(string);
return escapedString != null ? StringUtils.replaceBreakLinesBy(escapedString, " ") : "";
}
public static String removeAllWhiteCharacters(String text, String replacement) {
if (text == null) {
return null;
}
String replaced = text.replaceAll("(\\s)+", replacement);
return replaced;
}
public static Integer getNumberAsInteger(Number number) {
if (number != null) {
return new Long(Math.round(number.doubleValue())).intValue();
}
return null;
}
public boolean isInstance(Object object, String className) {
try {
Class<?> klass = Class.forName(className);
return klass.isInstance(object);
} catch (ClassNotFoundException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not find class with name '" + className + "'");
}
return false;
}
}
public Object e(BindingEvaluationContext context, String bindingExpression) {
return evaluateBinding(context, bindingExpression);
}
public Object eval(BindingEvaluationContext context, String bindingExpression) {
return evaluateBinding(context, bindingExpression);
}
public Object evaluate(BindingEvaluationContext context, String bindingExpression) {
return evaluateBinding(context, bindingExpression);
}
public Object evaluateBinding(BindingEvaluationContext context, String bindingExpression) {
if (context == null) {
return null;
}
if (bindingExpression == null) {
return null;
}
if (context instanceof EditionPatternInstance) {
return ((EditionPatternInstance) context).evaluate(bindingExpression);
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Binding evaluation not implemented for objects of type " + context.getClass().getName());
}
}
return null;
}
public void log(String s) {
if (logger.isLoggable(Level.INFO)) {
logger.info("LOG: " + s);
}
}
public void log(String s, Object o) {
if (logger.isLoggable(Level.INFO)) {
logger.info("LOG: " + s + " object=" + o + (o != null ? "(" + o.getClass().getSimpleName() + ")" : ""));
}
}
public void logO(Object o) {
if (o == null) {
if (logger.isLoggable(Level.INFO)) {
logger.info("LOG: object=null");
}
return;
}
if (logger.isLoggable(Level.INFO)) {
logger.info("LOG: object=" + o + " of " + o.getClass().getSimpleName());
}
}
public static void main(String[] args) {
String s = "²&é\"'(§è!çà)-_°0987654321³azertyuiop$^µùmlkjhgfdcsq<wxcvbn,;:=/*-+";
String xmlName = makeValidXMLName(s);
System.err.println(s);
System.err.println(xmlName);
System.err.println(s.length() + " " + xmlName.length());
}
}