/* * #%~ * org.overture.ide.debug * %% * Copyright (C) 2008 - 2014 Overture * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #~% */ package org.overture.ide.debug.core.model.internal; import java.util.Arrays; import org.eclipse.core.runtime.Assert; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IIndexedValue; import org.eclipse.debug.core.model.IVariable; import org.eclipse.osgi.util.NLS; import org.overture.ide.debug.core.VdmDebugManager; import org.overture.ide.debug.core.VdmDebugPlugin; import org.overture.ide.debug.core.dbgp.IDbgpProperty; import org.overture.ide.debug.core.dbgp.commands.IDbgpPropertyCommands; import org.overture.ide.debug.core.dbgp.exceptions.DbgpException; import org.overture.ide.debug.core.model.AtomicVdmType; import org.overture.ide.debug.core.model.CollectionVdmType; import org.overture.ide.debug.core.model.ComplexVdmType; import org.overture.ide.debug.core.model.IVdmStackFrame; import org.overture.ide.debug.core.model.IVdmThread; import org.overture.ide.debug.core.model.IVdmType; import org.overture.ide.debug.core.model.IVdmTypeFactory; import org.overture.ide.debug.core.model.IVdmValue; import org.overture.ide.debug.core.model.StringVdmType; import org.overture.ide.debug.core.model.eval.IVdmEvaluationCommand; import org.overture.ide.debug.core.model.eval.IVdmEvaluationEngine; import org.overture.ide.debug.core.model.internal.eval.VdmEvaluationCommand; public class VdmValue extends VdmDebugElement implements IVdmValue, IIndexedValue { static final IVariable[] NO_VARIABLES = new IVariable[0]; private final IVdmType type; final IVariable[] variables; private IVdmStackFrame frame; private int pageSize; private String name; private String fullname; private String value; private String details; private boolean hasChildren; private String key; private String rawValue; private String address; public static IVdmValue createValue(IVdmStackFrame frame, IDbgpProperty property) { IVdmType type = createType(frame.getDebugTarget(), property); return new VdmValue(frame, property, type); } private static IVdmType createType(IDebugTarget target, IDbgpProperty property) { IVdmType type = null; final String rawType = property.getType(); final IVdmTypeFactory factory = VdmDebugManager.getInstance().getTypeFactory(); if (factory != null) { type = factory.buildType(rawType); } else { type = new AtomicVdmType(rawType); } return type; } protected VdmValue(IVdmStackFrame frame, IDbgpProperty property, IVdmType type) { this.frame = frame; this.type = type; this.key = property.getKey(); this.name = property.getName(); this.fullname = property.getEvalName(); this.rawValue = property.getValue(); this.value = null; this.hasChildren = property.hasChildren(); this.pageSize = property.getPageSize(); this.address = property.getAddress(); final int childrenCount = property.getChildrenCount(); if (childrenCount > 0) { this.variables = new IVariable[childrenCount]; fillVariables(property.getPage(), property); } else { this.variables = NO_VARIABLES; } } private void loadPage(int page) throws DbgpException { IDbgpPropertyCommands commands = frame.getVdmThread().getDbgpSession().getCoreCommands(); IDbgpProperty pageProperty = null; if (key == null || key.length() == 0) { pageProperty = commands.getProperty(page, fullname, frame.getLevel()); } else { pageProperty = commands.getPropertyByKey(page, fullname, frame.getLevel(), key); } fillVariables(page, pageProperty); final int endIndex = Math.min((page + 1) * pageSize, variables.length); for (int i = page * pageSize; i < endIndex; ++i) { if (variables[i] == null) { variables[i] = new UnknownVariable(frame, this, i); } } } private void fillVariables(int page, IDbgpProperty pageProperty) { int offset = getPageOffset(page); IDbgpProperty[] properties = pageProperty.getAvailableChildren(); // if(pageProperty.getType().equals("map") && !pageProperty.getName().startsWith("Maplet")){ // properties = filterProperties(properties); // } final int size = Math.min(properties.length, variables.length - offset); if (size != properties.length) { VdmDebugPlugin.logWarning(NLS.bind("AvailableChildrenExceedsVariableLength", name), null); } if (size > 0) { for (int i = 0; i < size; ++i) { IDbgpProperty p = properties[i]; variables[offset + i] = new VdmVariable(frame, p.getName(), p); } if(rawValue!=null && !rawValue.startsWith("mk_")) { Arrays.sort(this.variables, offset, offset + size, VdmDebugManager.getInstance().getVariableNameComparator()); } } Assert.isLegal(pageSize > 0 || properties.length == variables.length); } // private IDbgpProperty[] filterProperties(IDbgpProperty[] properties) { // // ArrayList<IDbgpProperty> ret = new ArrayList<IDbgpProperty>(); // // for (IDbgpProperty iDbgpProperty : properties) { // if(iDbgpProperty.getName().startsWith("Maplet")) // ret.add(iDbgpProperty); // } // // // return (IDbgpProperty[]) ret.toArray(new IDbgpProperty[ret.size()]); // // } private int getPageOffset(int page) { if (pageSize <= 0) { pageSize = frame.getVdmThread().getPropertyPageSize(); } if (pageSize <= 0) { return 0; } return page * pageSize; } private int getPageForOffset(int offset) { Assert.isLegal(pageSize > 0); return offset / pageSize; } public String getReferenceTypeName() { return getType().getName(); } public String getValueString() { if (value == null || value.length() == 0) { value = getRawValue(); if (value.equals("seq") || value.equals("map") || value.equals("set")) { value = type.formatValue(this); } } if (type instanceof CollectionVdmType || type instanceof ComplexVdmType || type instanceof StringVdmType) { return type.getName(); } return value; } public String getDetailsString() { if (details == null || details.length() == 0) { details = type.formatDetails(this); } return details; } public String getRawValue() { return rawValue; } public String getEvalName() { return fullname; } public boolean hasVariables() { return hasChildren; } public boolean isAllocated() { return true; } public String toString() { return getValueString(); } public IDebugTarget getDebugTarget() { return frame.getDebugTarget(); } public String getInstanceId() { return key; } public IVdmType getType() { return type; } public IVdmEvaluationCommand createEvaluationCommand( String messageTemplate, IVdmThread thread) { IVdmEvaluationEngine engine = thread.getEvaluationEngine(); String pattern = "(%variable%)"; //$NON-NLS-1$ String evalName = getEvalName(); if (messageTemplate.indexOf(pattern) != -1) { String snippet = replacePattern(messageTemplate, pattern, evalName); return new VdmEvaluationCommand(engine, snippet, frame); } VdmDebugPlugin.logWarning(NLS.bind("detailFormatterRequiredToContainIdentifier", pattern), null); return new VdmEvaluationCommand(engine, evalName, frame); } private static String replacePattern(String messageTemplate, String pattern, String evalName) { String result = messageTemplate; while (result.indexOf(pattern) != -1) { int pos = result.indexOf(pattern); result = result.substring(0, pos) + evalName + result.substring(pos + pattern.length(), result.length()); } return result; } public int getInitialOffset() { return 0; } public int getSize() { return variables.length; } public IVariable getVariable(int offset) throws DebugException { try { if (variables[offset] == null) { loadPage(getPageForOffset(offset)); } return variables[offset]; } catch (DbgpException e) { throw wrapDbgpException(NLS.bind("unableToLoadChildrenOf", name), e); } } public IVariable[] getVariables() throws DebugException { return getVariables(0, getSize()); } public IVariable[] getVariables(int offset, int length) throws DebugException { IVariable[] variables = new IVariable[length]; for (int i = 0; i < length; i++) { variables[i] = getVariable(offset + i); } return variables; } public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { if (adapter == IIndexedValue.class && type.isCollection()) { return this; } return super.getAdapter(adapter); } public String getName() { return name; } /* * @see org.eclipse.dltk.debug.core.model.IVdmValue#getMemoryAddress() */ public String getMemoryAddress() { return address; } /** * Tests that some of the children are already created. * * @return */ protected boolean hasChildrenValuesLoaded() { for (int i = 0; i < variables.length; ++i) { if (variables[i] != null) { return true; } } return false; } }