001    package org.apache.commons.ognl;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.Collection;
023    import java.util.Map;
024    import java.util.Set;
025    
026    /**
027     * Implementation of PropertyAccessor that sets and gets properties by storing and looking up values in Maps.
028     *
029     * $Id: MapPropertyAccessor.java 1198666 2011-11-07 09:17:15Z mcucchiara $
030     * @author Luke Blanshard (blanshlu@netscape.net)
031     * @author Drew Davidson (drew@ognl.org)
032     */
033    public class MapPropertyAccessor
034        implements PropertyAccessor
035    {
036    
037        public Object getProperty( Map<String, Object> context, Object target, Object name )
038            throws OgnlException
039        {
040            Object result;
041            @SuppressWarnings( "unchecked" ) // checked by the invoker
042                Map<Object, Object> map = (Map<Object, Object>) target;
043            Node currentNode = ( (OgnlContext) context ).getCurrentNode().jjtGetParent();
044            boolean indexedAccess = false;
045    
046            if ( currentNode == null )
047            {
048                throw new OgnlException( "node is null for '" + name + "'" );
049            }
050            if ( !( currentNode instanceof ASTProperty ) )
051            {
052                currentNode = currentNode.jjtGetParent();
053            }
054            if ( currentNode instanceof ASTProperty )
055            {
056                indexedAccess = ( (ASTProperty) currentNode ).isIndexedAccess();
057            }
058    
059            if ( ( name instanceof String ) && !indexedAccess )
060            {
061                if ( "size".equals( name ) )
062                {
063                    result = map.size();
064                }
065                else if ( "keys".equals( name ) || "keySet".equals( name ) )
066                {
067                    result = map.keySet();
068                }
069                else if ( "values".equals( name ) )
070                {
071                    result = map.values();
072                }
073                else if ( "isEmpty".equals( name ) )
074                {
075                    result = map.isEmpty() ? Boolean.TRUE : Boolean.FALSE;
076                }
077                else
078                {
079                    result = map.get( name );
080                }
081            }
082            else
083            {
084                result = map.get( name );
085            }
086    
087            return result;
088        }
089    
090        public void setProperty( Map<String, Object> context, Object target, Object name, Object value )
091            throws OgnlException
092        {
093            @SuppressWarnings( "unchecked" ) // checked by the invoker
094            Map<Object, Object> map = (Map<Object, Object>) target;
095            map.put( name, value );
096        }
097    
098        public String getSourceAccessor( OgnlContext context, Object target, Object index )
099        {
100            Node currentNode = context.getCurrentNode().jjtGetParent();
101            boolean indexedAccess = false;
102    
103            if ( currentNode == null )
104            {
105                throw new RuntimeException( "node is null for '" + index + "'" );
106            }
107    
108            if ( !( currentNode instanceof ASTProperty ) )
109            {
110                currentNode = currentNode.jjtGetParent();
111            }
112    
113            if ( currentNode instanceof ASTProperty )
114            {
115                indexedAccess = ( (ASTProperty) currentNode ).isIndexedAccess();
116            }
117    
118            String indexStr = index.toString();
119    
120            context.setCurrentAccessor( Map.class );
121            context.setCurrentType( Object.class );
122    
123            if ( String.class.isInstance( index ) && !indexedAccess )
124            {
125                String key = indexStr.replaceAll( "\"", "" );
126    
127                if ( "size".equals( key ) )
128                {
129                    context.setCurrentType( int.class );
130                    return ".size()";
131                }
132                else if ( "keys".equals( key ) || "keySet".equals( key ) )
133                {
134                    context.setCurrentType( Set.class );
135                    return ".keySet()";
136                }
137                else if ( "values".equals( key ) )
138                {
139                    context.setCurrentType( Collection.class );
140                    return ".values()";
141                }
142                else if ( "isEmpty".equals( key ) )
143                {
144                    context.setCurrentType( boolean.class );
145                    return ".isEmpty()";
146                }
147            }
148    
149            return ".get(" + indexStr + ")";
150        }
151    
152        public String getSourceSetter( OgnlContext context, Object target, Object index )
153        {
154            context.setCurrentAccessor( Map.class );
155            context.setCurrentType( Object.class );
156    
157            String indexStr = index.toString();
158    
159            if ( String.class.isInstance( index ) )
160            {
161                String key = indexStr.replaceAll( "\"", "" );
162    
163                if ( "size".equals( key ) || "keys".equals( key ) || "keySet".equals( key ) || "values".equals( key )
164                    || "isEmpty".equals( key ) )
165                {
166                    return "";
167                }
168            }
169    
170            return ".put(" + indexStr + ", $3)";
171        }
172    }