/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG 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:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.e4.launcher.part;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.core.expressions.ElementHandler;
import org.eclipse.core.expressions.EvaluationContext;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionConverter;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.e4.core.commands.ECommandService;
import org.eclipse.e4.core.commands.EHandlerService;
import org.eclipse.e4.core.commands.ExpressionContext;
import org.eclipse.e4.core.commands.internal.HandlerServiceHandler;
import org.eclipse.e4.core.commands.internal.HandlerServiceImpl;
import org.eclipse.e4.core.contexts.ContextFunction;
import org.eclipse.e4.core.contexts.EclipseContextFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.InjectionException;
import org.eclipse.e4.ui.internal.workbench.Activator;
import org.eclipse.e4.ui.internal.workbench.Policy;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.ISourceProvider;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.e4.compatibility.E4Util;
import org.eclipse.ui.internal.expressions.AndExpression;
import org.eclipse.ui.internal.expressions.WorkbenchWindowExpression;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.services.EvaluationService;
import org.eclipse.ui.services.IEvaluationService;
import org.eclipse.ui.services.ISourceProviderService;
/**
* @since 3.5
*
*/
public class LegacyHandlerService implements IHandlerService {
private static final String[] SELECTION_VARIABLES = { ISources.ACTIVE_CURRENT_SELECTION_NAME, ISources.ACTIVE_FOCUS_CONTROL_ID_NAME,
ISources.ACTIVE_FOCUS_CONTROL_NAME, ISources.ACTIVE_MENU_EDITOR_INPUT_NAME, ISources.ACTIVE_MENU_NAME, ISources.ACTIVE_MENU_SELECTION_NAME };
public final static String LEGACY_H_ID = "legacy::handler::"; //$NON-NLS-1$
static class HandlerSelectionFunction extends ContextFunction {
private final String commandId;
/**
*
*/
public HandlerSelectionFunction(final String commandId) {
this.commandId = commandId;
}
@Override
public Object compute(final IEclipseContext context, final String contextKey) {
final HashSet<HandlerActivation> activationSet = new HashSet<HandlerActivation>();
IEclipseContext current = context;
while (current != null) {
final List<HandlerActivation> handlerActivations = (List<HandlerActivation>) current.getLocal(LEGACY_H_ID + commandId);
if (handlerActivations != null) {
activationSet.addAll(handlerActivations);
}
current = current.getParent();
}
if (activationSet.isEmpty()) {
return null;
}
HandlerActivation bestActivation = null;
final ExpressionContext legacyEvalContext = new ExpressionContext(context);
HandlerActivation conflictBest = null;
HandlerActivation conflictOther = null;
for (final HandlerActivation handlerActivation : activationSet) {
if (!handlerActivation.participating) {
continue;
}
if (handlerActivation.evaluate(legacyEvalContext)) {
if (bestActivation == null) {
bestActivation = handlerActivation;
} else {
final int comparison = bestActivation.compareTo(handlerActivation);
if (comparison < 0) {
bestActivation = handlerActivation;
} else if (comparison == 0) {
conflictBest = bestActivation;
conflictOther = handlerActivation;
}
}
}
}
if (bestActivation != null) {
if (bestActivation == conflictBest) {
WorkbenchPlugin.log("Conflicting handlers for " + commandId + ": {" //$NON-NLS-1$ //$NON-NLS-2$
+ conflictBest.getHandler() + "} vs {" //$NON-NLS-1$
+ conflictOther.getHandler() + "}"); //$NON-NLS-1$
}
return bestActivation.proxy;
}
return null;
}
}
private static IHandlerActivation systemHandlerActivation;
public static IHandlerActivation registerLegacyHandler(final IEclipseContext context, final String id, final String cmdId, final IHandler handler,
final Expression activeWhen) {
final ECommandService cs = (ECommandService) context.get(ECommandService.class.getName());
final Command command = cs.getCommand(cmdId);
final boolean handled = command.isHandled();
final boolean enabled = command.isEnabled();
final E4HandlerProxy handlerProxy = new E4HandlerProxy(command, handler);
final HandlerActivation activation = new HandlerActivation(context, cmdId, handler, handlerProxy, activeWhen);
addHandlerActivation(activation);
final EHandlerService hs = context.get(EHandlerService.class);
hs.activateHandler(cmdId, new HandlerSelectionFunction(cmdId));
final boolean handledChanged = handled != command.isHandled();
final boolean enabledChanged = enabled != command.isEnabled();
if (handledChanged || enabledChanged) {
// IHandler proxy = command.getHandler();
// TODO do we need to fire a handler changed event?
}
return activation;
}
static void addHandlerActivation(final HandlerActivation eActivation) {
List handlerActivations = (List) eActivation.context.getLocal(LEGACY_H_ID + eActivation.getCommandId());
if (handlerActivations == null) {
handlerActivations = new ArrayList();
} else {
if (handlerActivations.contains(eActivation)) {
return;
}
handlerActivations = new ArrayList(handlerActivations);
}
handlerActivations.add(eActivation);
// setting this so that we trigger invalidations
eActivation.context.set(LEGACY_H_ID + eActivation.getCommandId(), handlerActivations);
}
static void removeHandlerActivation(final HandlerActivation eActivation) {
List handlerActivations = (List) eActivation.context.getLocal(LEGACY_H_ID + eActivation.getCommandId());
if (handlerActivations == null) {
handlerActivations = new ArrayList();
} else {
handlerActivations = new ArrayList(handlerActivations);
}
handlerActivations.remove(eActivation);
// setting this so that we trigger invalidations
eActivation.context.set(LEGACY_H_ID + eActivation.getCommandId(), handlerActivations);
}
private final IEclipseContext eclipseContext;
private final IEvaluationContext evalContext;
private Expression defaultExpression = null;
public LegacyHandlerService(final IEclipseContext context) {
eclipseContext = context;
evalContext = new ExpressionContext(eclipseContext);
final IWorkbenchWindow window = (IWorkbenchWindow) eclipseContext.get(IWorkbenchWindow.class.getName());
if (window != null) {
defaultExpression = new WorkbenchWindowExpression(window);
}
}
public LegacyHandlerService(final IEclipseContext context, final Expression defaultExpression) {
eclipseContext = context;
evalContext = new ExpressionContext(eclipseContext);
this.defaultExpression = defaultExpression;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.services.IServiceWithSources#addSourceProvider(org.eclipse .ui.ISourceProvider)
*/
public void addSourceProvider(final ISourceProvider provider) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.services.IServiceWithSources#removeSourceProvider(org. eclipse.ui.ISourceProvider)
*/
public void removeSourceProvider(final ISourceProvider provider) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.services.IDisposable#dispose()
*/
public void dispose() {
E4Util.message("LegacyHandlerService.dispose: should it do something?"); //$NON-NLS-1$
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#activateHandler(org.eclipse.ui .handlers.IHandlerActivation)
*/
public IHandlerActivation activateHandler(final IHandlerActivation activation) {
if (activation == systemHandlerActivation) {
return activation;
}
final HandlerActivation handlerActivation = (HandlerActivation) activation;
handlerActivation.participating = true;
addHandlerActivation(handlerActivation);
return activation;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#activateHandler(java.lang.String, org.eclipse.core.commands.IHandler)
*/
public IHandlerActivation activateHandler(final String commandId, final IHandler handler) {
return activateHandler(commandId, handler, defaultExpression, false);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#activateHandler(java.lang.String, org.eclipse.core.commands.IHandler,
* org.eclipse.core.expressions.Expression)
*/
public IHandlerActivation activateHandler(final String commandId, final IHandler handler, final Expression expression) {
return activateHandler(commandId, handler, expression, false);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#activateHandler(java.lang.String, org.eclipse.core.commands.IHandler,
* org.eclipse.core.expressions.Expression, boolean)
*/
public IHandlerActivation activateHandler(final String commandId, final IHandler handler, final Expression expression, final boolean global) {
if (global || defaultExpression == null) {
return registerLegacyHandler(eclipseContext, commandId, commandId, handler, expression);
}
final AndExpression andExpr = new AndExpression();
andExpr.add(expression);
andExpr.add(defaultExpression);
return registerLegacyHandler(eclipseContext, commandId, commandId, handler, andExpr);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#activateHandler(java.lang.String, org.eclipse.core.commands.IHandler,
* org.eclipse.core.expressions.Expression, int)
*/
public IHandlerActivation activateHandler(final String commandId, final IHandler handler, final Expression expression, final int sourcePriorities) {
return activateHandler(commandId, handler, expression, false);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#createExecutionEvent(org.eclipse .core.commands.Command, org.eclipse.swt.widgets.Event)
*/
public ExecutionEvent createExecutionEvent(final Command command, final Event event) {
final EvaluationContext legacy = new EvaluationContext(evalContext, evalContext.getDefaultVariable());
final ExecutionEvent e = new ExecutionEvent(command, Collections.EMPTY_MAP, event, legacy);
return e;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#createExecutionEvent(org.eclipse .core.commands.ParameterizedCommand, org.eclipse.swt.widgets.Event)
*/
public ExecutionEvent createExecutionEvent(final ParameterizedCommand command, final Event event) {
final EvaluationContext legacy = new EvaluationContext(evalContext, evalContext.getDefaultVariable());
final ExecutionEvent e = new ExecutionEvent(command.getCommand(), command.getParameterMap(), event, legacy);
return e;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#deactivateHandler(org.eclipse .ui.handlers.IHandlerActivation)
*/
public void deactivateHandler(final IHandlerActivation activation) {
// null is not allowed, but some people put it anyway :( see bug 326406
if (activation != null && activation != systemHandlerActivation) {
final HandlerActivation eActivation = (HandlerActivation) activation;
eActivation.participating = false;
removeHandlerActivation(eActivation);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#deactivateHandlers(java.util. Collection)
*/
public void deactivateHandlers(final Collection activations) {
final Object[] array = activations.toArray();
// set all activations to not be participating first so that they ignore
// the upcoming context change events
for (int i = 0; i < array.length; i++) {
((HandlerActivation) array[i]).participating = false;
}
for (final Object element : array) {
deactivateHandler((IHandlerActivation) element);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#executeCommand(java.lang.String, org.eclipse.swt.widgets.Event)
*/
public Object executeCommand(final String commandId, final Event event) throws ExecutionException, NotDefinedException, NotEnabledException,
NotHandledException {
final ECommandService cs = eclipseContext.get(ECommandService.class);
final Command command = cs.getCommand(commandId);
return executeCommand(ParameterizedCommand.generateCommand(command, null), event);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#executeCommand(org.eclipse.core .commands.ParameterizedCommand, org.eclipse.swt.widgets.Event)
*/
public Object executeCommand(final ParameterizedCommand command, final Event event) throws ExecutionException, NotDefinedException, NotEnabledException,
NotHandledException {
final EHandlerService hs = eclipseContext.get(EHandlerService.class);
final IEclipseContext staticContext = EclipseContextFactory.create();
if (event != null) {
staticContext.set(Event.class, event);
}
try {
final Object rc = hs.executeHandler(command, staticContext);
final Object obj = staticContext.get(HandlerServiceImpl.HANDLER_EXCEPTION);
if (obj instanceof ExecutionException) {
throw (ExecutionException) obj;
} else if (obj instanceof NotDefinedException) {
throw (NotDefinedException) obj;
} else if (obj instanceof NotEnabledException) {
throw (NotEnabledException) obj;
} else if (obj instanceof NotHandledException) {
throw (NotHandledException) obj;
} else if (obj instanceof Exception) {
WorkbenchPlugin.log((Exception) obj);
}
return rc;
} catch (final InjectionException e) {
rethrow(e);
throw e;
} finally {
staticContext.dispose();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#executeCommandInContext(org.eclipse .core.commands.ParameterizedCommand, org.eclipse.swt.widgets.Event,
* org.eclipse.core.expressions.IEvaluationContext)
*/
public Object executeCommandInContext(final ParameterizedCommand command, final Event event, final IEvaluationContext context) throws ExecutionException,
NotDefinedException, NotEnabledException, NotHandledException {
final IHandler handler = command.getCommand().getHandler();
final boolean enabled = handler.isEnabled();
IEclipseContext staticContext = null;
Object defaultVar = null;
if (context instanceof ExpressionContext) {
// create a child context so that the primary context doesn't get
// populated by parameters by the EHS
staticContext = ((ExpressionContext) context).eclipseContext.createChild();
} else {
staticContext = eclipseContext.getActiveLeaf().createChild("snapshotContext"); //$NON-NLS-1$
if (event != null) {
staticContext.set(Event.class, event);
}
staticContext.set(IEvaluationContext.class, context);
defaultVar = context.getDefaultVariable();
if (defaultVar != null && defaultVar != IEvaluationContext.UNDEFINED_VARIABLE) {
staticContext.set(EvaluationService.DEFAULT_VAR, defaultVar);
}
}
final IEclipseContext lookupContext = staticContext;
// the IEvaluationContext snapshot is not part of our runtime
// IEclipseContext hierarchy. In order to work. we need the variables
// from the snapshot available in the static context.
populateSnapshot(context, staticContext);
final EHandlerService hs = lookupContext.get(EHandlerService.class);
try {
final Object rc = hs.executeHandler(command, staticContext);
final Object obj = staticContext.get(HandlerServiceImpl.HANDLER_EXCEPTION);
if (obj instanceof ExecutionException) {
throw (ExecutionException) obj;
} else if (obj instanceof NotDefinedException) {
throw (NotDefinedException) obj;
} else if (obj instanceof NotEnabledException) {
throw (NotEnabledException) obj;
} else if (obj instanceof NotHandledException) {
throw (NotHandledException) obj;
} else if (obj instanceof Exception) {
WorkbenchPlugin.log((Exception) obj);
}
return rc;
} catch (final InjectionException e) {
rethrow(e);
throw e;
} finally {
if (handler.isEnabled() != enabled && handler instanceof HandlerServiceHandler) {
((HandlerServiceHandler) handler).overrideEnabled(enabled);
}
staticContext.dispose();
}
}
/**
* @param context
* @param staticContext
*/
private void populateSnapshot(final IEvaluationContext context, final IEclipseContext staticContext) {
IEvaluationContext ctxPtr = context;
while (ctxPtr != null && !(ctxPtr instanceof ExpressionContext)) {
final Map vars = getVariables(ctxPtr);
if (vars != null) {
final Iterator i = vars.entrySet().iterator();
while (i.hasNext()) {
final Map.Entry entry = (Map.Entry) i.next();
if (staticContext.getLocal(entry.getKey().toString()) == null) {
staticContext.set(entry.getKey().toString(), entry.getValue());
}
}
}
ctxPtr = ctxPtr.getParent();
}
}
private Map getVariables(final IEvaluationContext ctx) {
final Field vars = getContextVariablesField();
if (vars != null) {
try {
return (Map) vars.get(ctx);
} catch (final IllegalArgumentException e) {
} catch (final IllegalAccessException e) {
}
}
return null;
}
private static Field contextFVariables = null;
private static Field getContextVariablesField() {
if (contextFVariables == null) {
try {
contextFVariables = EvaluationContext.class.getField("fVariables"); //$NON-NLS-1$
contextFVariables.setAccessible(true);
} catch (final SecurityException e) {
} catch (final NoSuchFieldException e) {
}
}
return contextFVariables;
}
/**
* Checks the cause of the provided exception and rethrows the cause instead if it was one of the expected exception types.
*/
private void rethrow(final InjectionException e) throws ExecutionException, NotDefinedException, NotEnabledException, NotHandledException {
final Throwable cause = e.getCause();
if (cause instanceof ExecutionException) {
throw (ExecutionException) cause;
} else if (cause instanceof NotDefinedException) {
throw (NotDefinedException) cause;
} else if (cause instanceof NotEnabledException) {
throw (NotEnabledException) cause;
} else if (cause instanceof NotHandledException) {
throw (NotHandledException) cause;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#createContextSnapshot(boolean)
*/
public IEvaluationContext createContextSnapshot(final boolean includeSelection) {
final IEvaluationContext tmpContext = getCurrentState();
final IEvaluationContext context = new EvaluationContext(null, IEvaluationContext.UNDEFINED_VARIABLE);
if (includeSelection) {
for (final String variable : SELECTION_VARIABLES) {
copyVariable(context, tmpContext, variable);
}
}
final ISourceProviderService sp = eclipseContext.get(ISourceProviderService.class);
for (final ISourceProvider provider : sp.getSourceProviders()) {
final String[] names = provider.getProvidedSourceNames();
for (final String name : names) {
if (!isSelectionVariable(name)) {
copyVariable(context, tmpContext, name);
}
}
}
return context;
}
private boolean isSelectionVariable(final String name) {
for (final String variable : SELECTION_VARIABLES) {
if (variable.equals(name)) {
return true;
}
}
return false;
}
private void copyVariable(final IEvaluationContext context, final IEvaluationContext tmpContext, final String var) {
final Object o = tmpContext.getVariable(var);
if (o != null) {
context.addVariable(var, o);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#getCurrentState()
*/
public IEvaluationContext getCurrentState() {
return new EvaluationContext(evalContext, evalContext.getDefaultVariable());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#readRegistry()
*/
public void readRegistry() {
readDefaultHandlers();
readHandlers();
}
private void readHandlers() {
final IExtensionRegistry registry = (IExtensionRegistry) eclipseContext.get(IExtensionRegistry.class.getName());
final IExtensionPoint extPoint = registry.getExtensionPoint(IWorkbenchRegistryConstants.EXTENSION_HANDLERS);
final IConfigurationElement[] elements = extPoint.getConfigurationElements();
for (final IConfigurationElement configElement : elements) {
final String commandId = configElement.getAttribute(IWorkbenchRegistryConstants.ATT_COMMAND_ID);
if (commandId == null || commandId.length() == 0) {
continue;
}
final String defaultHandler = configElement.getAttribute(IWorkbenchRegistryConstants.ATT_CLASS);
if ((defaultHandler == null) && (configElement.getChildren(IWorkbenchRegistryConstants.TAG_CLASS).length == 0)) {
continue;
}
Expression activeWhen = null;
final IConfigurationElement[] awChildren = configElement.getChildren(IWorkbenchRegistryConstants.TAG_ACTIVE_WHEN);
if (awChildren.length > 0) {
final IConfigurationElement[] subChildren = awChildren[0].getChildren();
if (subChildren.length != 1) {
Activator.trace(Policy.DEBUG_CMDS, "Incorrect activeWhen element " + commandId, null); //$NON-NLS-1$
continue;
}
final ElementHandler elementHandler = ElementHandler.getDefault();
final ExpressionConverter converter = ExpressionConverter.getDefault();
try {
activeWhen = elementHandler.create(converter, subChildren[0]);
} catch (final CoreException e) {
Activator.trace(Policy.DEBUG_CMDS, "Incorrect activeWhen element " + commandId, e); //$NON-NLS-1$
}
}
Expression enabledWhen = null;
final IConfigurationElement[] ewChildren = configElement.getChildren(IWorkbenchRegistryConstants.TAG_ENABLED_WHEN);
if (ewChildren.length > 0) {
final IConfigurationElement[] subChildren = ewChildren[0].getChildren();
if (subChildren.length != 1) {
Activator.trace(Policy.DEBUG_CMDS, "Incorrect enableWhen element " + commandId, null); //$NON-NLS-1$
continue;
}
final ElementHandler elementHandler = ElementHandler.getDefault();
final ExpressionConverter converter = ExpressionConverter.getDefault();
try {
enabledWhen = elementHandler.create(converter, subChildren[0]);
} catch (final CoreException e) {
Activator.trace(Policy.DEBUG_CMDS, "Incorrect enableWhen element " + commandId, e); //$NON-NLS-1$
}
}
registerLegacyHandler(eclipseContext, commandId, commandId, new HandlerProxy(commandId, configElement, IWorkbenchRegistryConstants.ATT_CLASS,
enabledWhen, eclipseContext.get(IEvaluationService.class)), activeWhen);
}
}
private void readDefaultHandlers() {
final IExtensionRegistry registry = (IExtensionRegistry) eclipseContext.get(IExtensionRegistry.class.getName());
final IExtensionPoint extPoint = registry.getExtensionPoint(IWorkbenchRegistryConstants.EXTENSION_COMMANDS);
final IConfigurationElement[] elements = extPoint.getConfigurationElements();
for (final IConfigurationElement configElement : elements) {
final String id = configElement.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
if (id == null || id.length() == 0) {
continue;
}
final String defaultHandler = configElement.getAttribute(IWorkbenchRegistryConstants.ATT_DEFAULT_HANDLER);
if ((defaultHandler == null) && (configElement.getChildren(IWorkbenchRegistryConstants.TAG_DEFAULT_HANDLER).length == 0)) {
continue;
}
registerLegacyHandler(eclipseContext, id, id, new HandlerProxy(id, configElement, IWorkbenchRegistryConstants.ATT_DEFAULT_HANDLER), null);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.handlers.IHandlerService#setHelpContextId(org.eclipse. core.commands.IHandler, java.lang.String)
*/
public void setHelpContextId(final IHandler handler, final String helpContextId) {
// TODO Auto-generated method stub
}
}