/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.qt.core.qmltypes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.internal.qt.core.Activator;
import org.eclipse.cdt.qt.core.qmljs.IJSArrayExpression;
import org.eclipse.cdt.qt.core.qmljs.IJSExpression;
import org.eclipse.cdt.qt.core.qmljs.IQmlASTNode;
import org.eclipse.cdt.qt.core.qmljs.IQmlBinding;
import org.eclipse.cdt.qt.core.qmljs.IQmlProgram;
import org.eclipse.cdt.qt.core.qmljs.IQmlPropertyBinding;
import org.eclipse.cdt.qt.core.qmljs.IQmlQualifiedID;
import org.eclipse.cdt.qt.core.qmljs.IQmlRootObject;
import org.eclipse.cdt.qt.core.qmljs.IQmlScriptBinding;
import org.eclipse.cdt.qt.core.qmljs.QMLExpressionEvaluator;
import org.eclipse.cdt.qt.core.qmljs.QMLExpressionEvaluator.InvalidExpressionException;
public class QMLModelBuilder {
private final Map<String, QMLModuleInfo> moduleMap = new HashMap<>();
public QMLModelBuilder() {
}
public QMLModuleInfo addModule(String module, IQmlASTNode ast) {
QMLModuleInfo info = moduleMap.get(module);
if (!moduleMap.containsKey(module)) {
if (ensureNode(ast, IQmlProgram.class)) {
IQmlRootObject obj = ((IQmlProgram) ast).getRootObject();
if (ensureNode(obj, IQmlRootObject.class)) {
info = new QMLModuleInfo(this, obj);
moduleMap.put(module, info);
}
}
}
return info;
}
public QMLModuleInfo getModule(String module) {
return moduleMap.get(module);
}
public boolean hasModule(String module) {
return moduleMap.get(module) != null;
}
boolean ensureIdentifier(IQmlQualifiedID actual, String expected) {
if (!actual.getName().equals(expected)) {
Activator.log("[QmlTypes] Unexpected node identifier: expected '" + expected + "', but was '" //$NON-NLS-1$ //$NON-NLS-2$
+ actual.getName() + "'"); //$NON-NLS-1$
return false;
}
return true;
}
boolean ensureNode(IQmlASTNode actual, Class<? extends IQmlASTNode> expected) {
if (!expected.isInstance(actual)) {
Activator.log("[QmlTypes] Expected node '" + expected + "', but was '" + actual.getClass().getInterfaces()[0] + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return false;
}
return true;
}
boolean ensureValue(Object actual, Class<?> expected) {
if (!expected.isInstance(actual)) {
Activator.log("[QmlTypes] Unexpected value: expected '" + expected + "', but was '" //$NON-NLS-1$ //$NON-NLS-2$
+ actual.getClass().getInterfaces()[0] + "'"); //$NON-NLS-1$
return false;
}
return true;
}
void unexpectedNode(IQmlASTNode node) {
Activator.log("[QmlTypes] Unexpected node '" + node.getClass().getInterfaces()[0] + "'"); //$NON-NLS-1$ //$NON-NLS-2$
}
String getStringBinding(IQmlPropertyBinding prop) {
IQmlBinding b = prop.getBinding();
if (ensureNode(b, IQmlScriptBinding.class)) {
IQmlScriptBinding sb = (IQmlScriptBinding) b;
if (ensureNode(sb.getScript(), IJSExpression.class)) {
try {
Object value = QMLExpressionEvaluator.evaluateConstExpr((IJSExpression) sb.getScript());
if (value instanceof String) {
return (String) value;
}
} catch (InvalidExpressionException e) {
handleException(e);
}
}
}
return null;
}
String[] getStringArrayBinding(IQmlPropertyBinding prop) {
ArrayList<String> result = new ArrayList<>();
IQmlBinding b = prop.getBinding();
if (ensureNode(b, IQmlScriptBinding.class)) {
IQmlScriptBinding sb = (IQmlScriptBinding) b;
if (ensureNode(sb.getScript(), IJSArrayExpression.class)) {
IJSArrayExpression arrExpr = (IJSArrayExpression) sb.getScript();
for (IJSExpression expr : arrExpr.getElements()) {
try {
Object value = QMLExpressionEvaluator.evaluateConstExpr(expr);
if (value instanceof String) {
result.add((String) value);
}
} catch (InvalidExpressionException e) {
handleException(e);
}
}
}
}
return result.toArray(new String[result.size()]);
}
public Integer[] getIntegerArrayBinding(IQmlPropertyBinding prop) {
ArrayList<Integer> result = new ArrayList<>();
IQmlBinding b = prop.getBinding();
if (ensureNode(b, IQmlScriptBinding.class)) {
IQmlScriptBinding sb = (IQmlScriptBinding) b;
if (ensureNode(sb.getScript(), IJSArrayExpression.class)) {
IJSArrayExpression arrExpr = (IJSArrayExpression) sb.getScript();
for (IJSExpression expr : arrExpr.getElements()) {
try {
Object value = QMLExpressionEvaluator.evaluateConstExpr(expr);
if (value instanceof Number) {
result.add(((Number) value).intValue());
}
} catch (InvalidExpressionException e) {
handleException(e);
}
}
}
}
return result.toArray(new Integer[result.size()]);
}
boolean getBooleanBinding(IQmlPropertyBinding prop) {
IQmlBinding b = prop.getBinding();
if (ensureNode(b, IQmlScriptBinding.class)) {
IQmlScriptBinding sb = (IQmlScriptBinding) b;
if (ensureNode(sb.getScript(), IJSExpression.class)) {
try {
Object value = QMLExpressionEvaluator.evaluateConstExpr((IJSExpression) sb.getScript());
if (value instanceof Number) {
return (Boolean) value;
}
} catch (InvalidExpressionException e) {
handleException(e);
}
}
}
return false;
}
public Integer getIntegerBinding(IQmlPropertyBinding prop) {
IQmlBinding b = prop.getBinding();
if (ensureNode(b, IQmlScriptBinding.class)) {
IQmlScriptBinding sb = (IQmlScriptBinding) b;
if (ensureNode(sb.getScript(), IJSExpression.class)) {
try {
Object value = QMLExpressionEvaluator.evaluateConstExpr((IJSExpression) sb.getScript());
if (value instanceof Number) {
return ((Number) value).intValue();
}
} catch (InvalidExpressionException e) {
handleException(e);
}
}
}
return 0;
}
public void handleException(Throwable t) {
Activator.log("[QmlTypes] " + t.getMessage()); //$NON-NLS-1$
}
}