/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.portal.datasource.el; import java.io.IOException; import java.io.Reader; import java.io.StreamTokenizer; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.List; import org.apache.commons.lang.StringUtils; import org.joda.time.DateTime; import org.joda.time.Period; import org.joda.time.format.ISOPeriodFormat; import org.joda.time.format.PeriodFormatter; import com.enonic.cms.core.portal.PortalInstanceKey; import com.enonic.cms.core.portal.page.PageRequestFactory; import com.enonic.cms.core.preference.PreferenceEntity; import com.enonic.cms.core.preference.PreferenceKey; import com.enonic.cms.core.preference.PreferenceScope; import com.enonic.cms.core.preference.PreferenceScopeKey; import com.enonic.cms.core.preference.PreferenceScopeKeyResolver; import com.enonic.cms.core.preference.PreferenceScopeResolver; import com.enonic.cms.core.preference.PreferenceScopeType; import com.enonic.cms.core.preference.PreferenceService; import com.enonic.cms.core.structure.menuitem.MenuItemEntity; import com.enonic.cms.core.structure.menuitem.MenuItemKeysByPathResolver; import com.enonic.cms.core.structure.portlet.PortletKey; import com.enonic.cms.core.time.TimeService; import com.enonic.cms.store.dao.MenuItemDao; /** * */ public class ExpressionFunctions { private PreferenceService preferenceService; private ExpressionContext context; private TimeService timeService; private MenuItemDao menuItemDao; public boolean isnotblank( String str ) { return StringUtils.isNotBlank( str ); } public boolean isblank( String str ) { return StringUtils.isBlank( str ); } public boolean isnotempty( String str ) { return StringUtils.isNotEmpty( str ); } public boolean isempty( String str ) { return StringUtils.isEmpty( str ); } /** * Select the first value that is not null and not empty. * * @param s1 The first value checked * @param s2 The second value. * @return The first value, if it is not null or empty. Otherwise, the second value, no matter what it is. */ public String select( String s1, String s2 ) { if ( s1 == null ) { return s2; } else if ( s1.trim().length() > 0 ) { return s1; } else { return s2; } } public String concat( String... str ) { StringBuilder sb = new StringBuilder(); for ( String s : str ) { sb.append( s ); } return sb.toString(); } public String replace( String source, String regex, String replacement ) { return source.replaceAll( regex, replacement ); } public String substring( String source, int beginIndex, int endIndex ) { return source.substring( beginIndex, endIndex ); } public int stringlength( String source ) { return source != null ? source.length() : 0; } public String lower( String source ) { return source.toLowerCase(); } public String upper( String source ) { return source.toUpperCase(); } public String trim( String source ) { return source.trim(); } public int min( int v1, int v2 ) { return Math.min( v1, v2 ); } public int max( int v1, int v2 ) { return Math.max( v1, v2 ); } public String currentDate( String format ) { SimpleDateFormat fmt = new SimpleDateFormat( format ); return fmt.format( timeService.getNowAsDateTime().toDate() ); } public String currentDatePlusOffset( String format, String periodStr ) { DateTime nowDateTime = timeService.getNowAsDateTime(); PeriodFormatter periodFormatter = ISOPeriodFormat.standard(); Period period = periodFormatter.parsePeriod( periodStr ); DateTime offsetDateTime = nowDateTime.plus( period ); SimpleDateFormat fmt = new SimpleDateFormat( format ); return fmt.format( offsetDateTime.toDate() ); } public String currentDateMinusOffset( String format, String periodStr ) { DateTime nowDateTime = timeService.getNowAsDateTime(); PeriodFormatter periodFormatter = ISOPeriodFormat.standard(); Period period = periodFormatter.parsePeriod( periodStr ); DateTime offsetDateTime = nowDateTime.minus( period ); SimpleDateFormat fmt = new SimpleDateFormat( format ); return fmt.format( offsetDateTime.toDate() ); } public String periodHoursMinutes( int hours, int minutes ) { Period period = new Period( hours, minutes, 0, 0 ); return period.toString(); } public String pref( String scope, String key ) { if ( context.getUser() == null || context.getUser().isAnonymous() ) { return ""; } final PortletKey portletKey = PageRequestFactory.getPageRequest().getCurrentPortletKey(); PreferenceEntity preferenceEntity = getPreferenceEntity( scope, portletKey, key ); return preferenceEntity != null ? preferenceEntity.getValue() : ""; } private PreferenceEntity getPreferenceEntity( String scope, PortletKey portletKey, String key ) { PreferenceEntity preferenceEntity = null; PreferenceScopeKey scopeKey; PreferenceScopeType scopeType = PreferenceScopeType.parse( scope ); PortalInstanceKey instanceKey = context.getPortalInstanceKey(); if ( scopeType != null ) { /* Scope supplied - try with supplied key and nothing else... */ scopeKey = PreferenceScopeKeyResolver.resolve( scopeType, instanceKey, instanceKey.getSiteKey() ); preferenceEntity = preferenceService.getPreference( new PreferenceKey( context.getUser().getKey(), scopeType, scopeKey, key ) ); } else { /* No scope supplied - try to resolve scope and find preference... */ List<PreferenceScope> scopes = PreferenceScopeResolver.resolveAllScopes( instanceKey, instanceKey.getSiteKey() ); for ( int i = 0; i < scopes.size() && preferenceEntity == null; i++ ) { preferenceEntity = preferenceService.getPreference( new PreferenceKey( context.getUser().getKey(), scopes.get( i ), key ) ); } } return preferenceEntity; } /** * This method will take a freetext search string and create a valid query that can be used in the getContent* methods. The search * string is spilt into tokens. Using the operator, it may be specified whether the field must contain all or any of the words in the * search string. * * @param fieldName The name of the field to search for the words in the search string. * @param searchString The words to search for. * @param operator Must be either AND or OR. Case doesn't matter. * @return A syntactically correct search that may be used as the query parameter in getContent* methods on the data source. With care, * it may also be merged with other queries using AND or OR. * @throws IllegalArgumentException If any of the parameters are empty or the operator is not AND or OR. */ public String buildFreetextQuery( String fieldName, String searchString, String operator ) { if ( searchString == null || searchString.trim().equals( "" ) ) { return ""; } if ( fieldName == null || fieldName.trim().equals( "" ) ) { throw new IllegalArgumentException( "fieldName can not be empty." ); } String op = ""; if ( operator != null ) { op = operator.trim().toUpperCase(); } if ( !( op.equals( "AND" ) || op.equals( "OR" ) ) ) { throw new IllegalArgumentException( "Illegal operator: " + operator ); } boolean first = true; StringBuilder queryTokens = new StringBuilder(); Reader searchStringReader = new StringReader( searchString ); StreamTokenizer searchStringTokens = new StreamTokenizer( searchStringReader ); searchStringTokens.slashSlashComments( false ); searchStringTokens.slashStarComments( false ); searchStringTokens.eolIsSignificant( false ); searchStringTokens.ordinaryChar( '!' ); searchStringTokens.ordinaryChars( '#', '}' ); searchStringTokens.wordChars( '!', '!' ); searchStringTokens.wordChars( '#', '}' ); try { while ( searchStringTokens.nextToken() != StreamTokenizer.TT_EOF ) { String token = searchStringTokens.sval; addQueryPart( queryTokens, first, fieldName, token, op ); if ( first ) { first = false; } } } catch ( IOException e ) { throw new IllegalStateException( "This should never happen, since the IO class is wrapping a string!" ); } return queryTokens.toString(); } public String getPageKey() { return context.getMenuItem().getKey().toString(); } public String getWindowKey() { return context.getPortalInstanceKey().getWindowKey().asString(); } private void addQueryPart( StringBuilder query, boolean first, String fieldName, String token, String op ) { if ( !first ) { query.append( ' ' ); query.append( op ); query.append( ' ' ); } query.append( fieldName ); query.append( " CONTAINS \"" ); query.append( token ); query.append( "\"" ); } public String getPageKeyByPath( String path ) { MenuItemEntity menuItem = menuItemDao.findByKey( context.getMenuItem().getKey() ); MenuItemKeysByPathResolver menuItemKeysByPathResolver = new MenuItemKeysByPathResolver( menuItem ); return menuItemKeysByPathResolver.getPageKeyByPath( path ); } public String getPageKeysByPath( String path ) { MenuItemEntity menuItem = menuItemDao.findByKey( context.getMenuItem().getKey() ); MenuItemKeysByPathResolver menuItemKeysByPathResolver = new MenuItemKeysByPathResolver( menuItem ); return menuItemKeysByPathResolver.getPageKeysByPath( path ); } public void setPreferenceService( PreferenceService preferenceService ) { this.preferenceService = preferenceService; } public void setContext( ExpressionContext context ) { this.context = context; } public void setTimeService( TimeService timeService ) { this.timeService = timeService; } public void setMenuItemDao( MenuItemDao menuItemDao ) { this.menuItemDao = menuItemDao; } public String urlEncode( String source ) { if ( StringUtils.isBlank( source ) ) { return ""; } try { return URLEncoder.encode( source, "UTF-8" ); } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } } }