001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.script.el.tokens;
020:
021: import java.util.Map;
022:
023: import org.apache.beehive.netui.util.internal.InternalStringBuilder;
024: import org.apache.beehive.netui.util.logging.Logger;
025:
026: /**
027: * Token that represents a Map lookup token.
028: */
029: public class MapKeyToken extends ExpressionToken {
030:
031: private static final Logger LOGGER = Logger
032: .getInstance(MapKeyToken.class);
033:
034: private String _identifier = null;
035: private char _quoteChar = '\'';
036:
037: public MapKeyToken(String identifier) {
038: assert identifier != null;
039: assert identifier.length() >= 2;
040:
041: if (identifier.startsWith("\""))
042: _quoteChar = '"';
043: // convert the Java string to an EcmaScript string. Strip the quotes that exist because they're
044: // always there for this token.
045: _identifier = convertToEcmaScriptString(identifier.substring(1,
046: identifier.length() - 1));
047: }
048:
049: /**
050: * Given a Java String, this value needs to be converted into a JavaScript compliant String.
051: * See JavaScript: The Definitive Guide for how to do this
052: */
053: private String convertToEcmaScriptString(String string) {
054: int len = string.length();
055: InternalStringBuilder buf = new InternalStringBuilder(len);
056: for (int i = 0; i < len; i++) {
057: char c = string.charAt(i);
058: // skip the \\ and consume the next character either appending it or turning it back
059: // into the single character that it should have been in the first place.
060:
061: // if slash and not at the last character...
062: if (c == '\\' && i + 1 < len) {
063: i++;
064:
065: // skip the slash
066: c = string.charAt(i);
067:
068: if (c == 'b')
069: c = '\b';
070: else if (c == 't')
071: c = '\t';
072: else if (c == 'n')
073: c = '\n';
074: //else if(c == 'v') c = '\v';
075: else if (c == 'f')
076: c = '\f';
077: else if (c == 'r')
078: c = '\r';
079: // @todo: unicode escaping?
080: }
081:
082: buf.append(c);
083: }
084:
085: LOGGER
086: .trace("converted String to JavaScript compliant string: "
087: + buf.toString());
088:
089: return buf.toString();
090: }
091:
092: /**
093: * Read the value represented by this token from the given <code>object</code>.
094: * @param object the object
095: * @return the value of this property on object
096: */
097: public Object read(Object object) {
098: if (object instanceof Map)
099: return mapLookup((Map) object, _identifier);
100: else
101: return beanLookup(object, _identifier);
102: }
103:
104: /**
105: * Update a the value represented by this token on the given <code>object</code> with the
106: * new value.
107: * @param object the object
108: * @param value the new value of this property on the object
109: */
110: public void write(Object object, Object value) {
111: if (object instanceof Map)
112: mapUpdate((Map) object, _identifier, value);
113: else
114: beanUpdate(object, _identifier, value);
115: }
116:
117: public String getTokenString() {
118: return _quoteChar + _identifier + _quoteChar;
119: }
120:
121: public String toString() {
122: return _identifier;
123: }
124: }
|