All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.jasperreports.engine.design.JRDesignExpression Maven / Gradle / Ivy

There is a newer version: 6.21.3
Show newest version
/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of JasperReports.
 *
 * JasperReports is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JasperReports 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JasperReports. If not, see .
 */

/*
 * Contributors:
 * Ryan Johnson - [email protected] 
 */
package net.sf.jasperreports.engine.design;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import net.sf.jasperreports.annotations.properties.Property;
import net.sf.jasperreports.annotations.properties.PropertyScope;
import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRConstants;
import net.sf.jasperreports.engine.JRExpressionChunk;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.base.JRBaseExpression;
import net.sf.jasperreports.engine.design.events.JRChangeEventsSupport;
import net.sf.jasperreports.engine.design.events.JRPropertyChangeSupport;
import net.sf.jasperreports.engine.type.ExpressionTypeEnum;
import net.sf.jasperreports.engine.util.ExpressionParser;
import net.sf.jasperreports.engine.util.JRCloneUtils;
import net.sf.jasperreports.properties.PropertyConstants;


/**
 * @author Teodor Danciu ([email protected])
 */
public class JRDesignExpression extends JRBaseExpression implements JRChangeEventsSupport
{
	/**
	 *
	 */
	private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID;

	/**
	 * Property that specifies whether a legacy parser method should be used to parse this expression. Default value is false.
	 */
	@Property(
			category = PropertyConstants.CATEGORY_COMPILE,
			defaultValue = PropertyConstants.BOOLEAN_FALSE,
			scopes = {PropertyScope.CONTEXT},
			sinceVersion = PropertyConstants.VERSION_5_5_2,
			valueType = Boolean.class
			)
	public static final String PROPERTY_LEGACY_PARSER = 
			JRPropertiesUtil.PROPERTY_PREFIX + "legacy.expression.parser";
	
	protected static final boolean LEGACY_PARSER;
	static
	{
		JRPropertiesUtil properties = JRPropertiesUtil.getInstance(DefaultJasperReportsContext.getInstance());
		LEGACY_PARSER = properties.getBooleanProperty(PROPERTY_LEGACY_PARSER, false);
	}
	
	/**
	 * @deprecated moved to {@link ExpressionParser#PLACEHOLDER_PATTERN}
	 */
	@Deprecated
	public static final Pattern PLACEHOLDER_PATTERN = ExpressionParser.PLACEHOLDER_PATTERN;
	
	public static final String PROPERTY_TEXT = "text";
	
	/**
	 * @deprecated To be removed.
	 */
	public static final String PROPERTY_VALUE_CLASS_NAME = "valueClassName";

	/**
	 *
	 */
	protected List chunks = new ArrayList();


	/**
	 *
	 */
	public JRDesignExpression()
	{
		super();

		regenerateId();
	}


	/**
	 *
	 */
	public JRDesignExpression(String text)
	{
		this();

		setText(text);
	}


	/**
	 * @deprecated To be removed.
	 */
	public void setValueClass(Class clazz)
	{
		setValueClassName(clazz.getName());
	}

	/**
	 * @deprecated To be removed.
	 */
	public void setValueClassName(String className)
	{
		Object old = this.valueClassName;
		valueClassName = className;
		valueClass = null;
		valueClassRealName = null;
		getEventSupport().firePropertyChange(PROPERTY_VALUE_CLASS_NAME, old, this.valueClassName);
	}

	/**
	 * FIXMENOW remove me?
	 */
	public void setId(int id)
	{
		this.id = id;
	}

	/**
	 *
	 */
	public void setType(ExpressionTypeEnum type)
	{
		this.type = type; //FIXMENOW why not raise change event?
	}

	@Override
	public JRExpressionChunk[] getChunks()
	{
		JRExpressionChunk[] chunkArray = null;
		
		if (chunks != null && chunks.size() > 0)
		{
			chunkArray = new JRExpressionChunk[chunks.size()];
			chunks.toArray(chunkArray);
		}
		
		return chunkArray;
	}
		
	/**
	 * Clears the current list of chunks and adds the passed list of chunks.  The reference
	 * to the list passed is not kept.
	 */
	public void setChunks(List chunks)
	{
		this.chunks.clear();
		this.chunks.addAll(chunks);
	}

	/**
	 *
	 */
	public void addChunk(JRDesignExpressionChunk chunk)
	{
		this.chunks.add(chunk);
	}
		
	protected void addChunk(byte type, String text)
	{
		JRDesignExpressionChunk chunk = new JRDesignExpressionChunk();
		chunk.setType(type);
		chunk.setText(text);
		
		this.chunks.add(chunk);
	}
		
	/**
	 *
	 */
	public void addTextChunk(String text)
	{
		JRDesignExpressionChunk chunk = new JRDesignExpressionChunk();
		chunk.setType(JRExpressionChunk.TYPE_TEXT);
		chunk.setText(text);
		
		this.chunks.add(chunk);
	}
		
	/**
	 *
	 */
	public void addParameterChunk(String text)
	{
		JRDesignExpressionChunk chunk = new JRDesignExpressionChunk();
		chunk.setType(JRExpressionChunk.TYPE_PARAMETER);
		chunk.setText(text);
		
		this.chunks.add(chunk);
	}
		
	/**
	 *
	 */
	public void addFieldChunk(String text)
	{
		JRDesignExpressionChunk chunk = new JRDesignExpressionChunk();
		chunk.setType(JRExpressionChunk.TYPE_FIELD);
		chunk.setText(text);
		
		this.chunks.add(chunk);
	}
		
	/**
	 *
	 */
	public void addVariableChunk(String text)
	{
		JRDesignExpressionChunk chunk = new JRDesignExpressionChunk();
		chunk.setType(JRExpressionChunk.TYPE_VARIABLE);
		chunk.setText(text);
		
		this.chunks.add(chunk);
	}

	/**
	 *
	 */
	public void addResourceChunk(String text)
	{
		JRDesignExpressionChunk chunk = new JRDesignExpressionChunk();
		chunk.setType(JRExpressionChunk.TYPE_RESOURCE);
		chunk.setText(text);
		
		this.chunks.add(chunk);
	}

	/**
	 *
	 */
	public void setText(String text)
	{
		Object old = getText();
		
		chunks.clear();
		
		if (text != null)
		{
			if (LEGACY_PARSER)
			{
				//FIXME remove this at some point
				legacyParseText(text);
			}
			else
			{
				parseText(text);
			}
		}
		
		getEventSupport().firePropertyChange(PROPERTY_TEXT, old, text);
	}

	protected void legacyParseText(String text)
	{
		StringBuilder textChunk = new StringBuilder();
		
		StringTokenizer tkzer = new StringTokenizer(text, "$", true);
		int behindDelims = 0;
		while (tkzer.hasMoreTokens())
		{
			String token = tkzer.nextToken();

			if (token.equals("$"))
			{
				if (behindDelims > 0)
				{
					textChunk.append("$");
				}

				++behindDelims;
			}
			else
			{
				byte chunkType = JRExpressionChunk.TYPE_TEXT;
				if (behindDelims > 0)
				{
					if (token.startsWith("P{"))
					{
						chunkType = JRExpressionChunk.TYPE_PARAMETER;
					}
					else if (token.startsWith("F{"))
					{
						chunkType = JRExpressionChunk.TYPE_FIELD;
					}
					else if (token.startsWith("V{"))
					{
						chunkType = JRExpressionChunk.TYPE_VARIABLE;
					}
					else if (token.startsWith("R{"))
					{
						chunkType = JRExpressionChunk.TYPE_RESOURCE;
					}
				}
				
				if (chunkType == JRExpressionChunk.TYPE_TEXT)
				{
					if (behindDelims > 0)
					{
						textChunk.append("$");
					}
					textChunk.append(token);
				}
				else
				{
					int end = token.indexOf('}');
					if (end > 0)
					{
						if (behindDelims > 1)
						{
							textChunk.append(token);
						}
						else
						{
							if (textChunk.length() > 0)
							{
								addTextChunk(textChunk.toString());					
							}
							
							addChunk(chunkType, token.substring(2, end));					
							textChunk = new StringBuilder(token.substring(end + 1));
						}
					}
					else
					{
						if (behindDelims > 0)
						{
							textChunk.append("$");
						}
						textChunk.append(token);
					}
				}

				behindDelims = 0;
			}
		}

		if (behindDelims > 0)
		{
			textChunk.append("$");
		}

		if (textChunk.length() > 0)
		{
			this.addTextChunk(textChunk.toString());					
		}
	}
	
	protected void parseText(String text)
	{
		ExpressionParser.instance().parseExpression(text, new ExpressionParser.ParseResult()
		{
			@Override
			public void addTextChunk(String text)
			{
				JRDesignExpression.this.addTextChunk(text);
			}
			
			@Override
			public void addChunk(byte chunkType, String chunkText)
			{
				JRDesignExpression.this.addChunk(chunkType, chunkText);
			}
		});
	}

	private transient JRPropertyChangeSupport eventSupport;
	
	@Override
	public JRPropertyChangeSupport getEventSupport()
	{
		synchronized (this)
		{
			if (eventSupport == null)
			{
				eventSupport = new JRPropertyChangeSupport(this);
			}
		}
		
		return eventSupport;
	}

	@Override
	public Object clone() 
	{
		JRDesignExpression clone = (JRDesignExpression)super.clone();
		clone.chunks = JRCloneUtils.cloneList(chunks);
		clone.eventSupport = null;
		return clone;
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy