// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.sdk.internal.v8native.value; import org.chromium.sdk.JsValue.Type; import org.chromium.sdk.JsObjectProperty; import org.chromium.sdk.JsVariable; /** * A generic implementation of the JsVariable interface. */ public class JsVariableImpl implements JsVariable { /** The fully qualified name of this variable. */ private final String qualifiedName; /** The lazily constructed value of this variable. */ private final JsValueBase value; /** Variable name. */ private final Object rawName; /** Variable name. */ private final String decoratedName; /** * Constructs a variable contained in the given context with the given * value mirror. * * @param valueLoader that owns this variable * @param valueData value data for this variable */ public JsVariableImpl(ValueLoader valueLoader, ValueMirror valueData, String name) { this(valueLoader, valueData, name, name, name); } /** * Constructs a variable contained in the given context with the given * value mirror. * * @param valueLoader that owns this variable * @param valueData for this variable * @param qualifiedName the fully qualified name of this variable */ JsVariableImpl(ValueLoader valueLoader, ValueMirror valueData, Object rawName, String decoratedName, String qualifiedName) { this.rawName = rawName; this.decoratedName = decoratedName; this.qualifiedName = qualifiedName; this.value = createValue(valueLoader, valueData, qualifiedName); } public static JsValueBase createValue(ValueLoader valueLoader, ValueMirror valueData, String qualifiedName) { Type type = valueData.getType(); switch (type) { case TYPE_FUNCTION: return new JsFunctionImpl(valueLoader, qualifiedName, valueData); case TYPE_ERROR: case TYPE_OBJECT: return new JsObjectBase.Impl(valueLoader, qualifiedName, valueData); case TYPE_ARRAY: return new JsArrayImpl(valueLoader, qualifiedName, valueData); default: return new JsValueBase.Impl(valueData); } } /** * @return a [probably compound] JsValue corresponding to this variable. * {@code null} if there was an error lazy-loading the value data. */ @Override public JsValueBase getValue() { return value; } @Override public String getName() { return decoratedName; } public String getRawName() { return this.rawName.toString(); } Object getRawNameAsObject() { return this.rawName; } @Override public boolean isMutable() { return false; // TODO(apavlov): fix once V8 supports it } @Override public boolean isReadable() { // TODO(apavlov): implement once the readability metadata are available return true; } @Override public synchronized void setValue(String newValue, SetValueCallback callback) { // TODO(apavlov): currently V8 does not support it if (!isMutable()) { throw new UnsupportedOperationException(); } } @Override public JsObjectProperty asObjectProperty() { return null; } @Override public String toString() { return new StringBuilder() .append("[JsVariable: name=") .append(getName()) .append(",value=") .append(getValue()) .append(']') .toString(); } @Override public String getFullyQualifiedName() { return qualifiedName != null ? qualifiedName : getName(); } static class NameDecorator { static String decorateVarName(Object rawName) { if (rawName instanceof Number) { return OPEN_BRACKET + rawName + CLOSE_BRACKET; } else { return rawName.toString(); } } static String buildAccessSuffix(Object rawName) { if (rawName instanceof Number) { return OPEN_BRACKET + rawName + CLOSE_BRACKET; } else { return "." + rawName; } } private static final String OPEN_BRACKET = "["; private static final String CLOSE_BRACKET = "]"; } }