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 }