/** * Specialized stack-like structure that allows for multiple stacks based on a key. Each key * passed into the <code>KeyedStack</code> is given a unique <code>Stack</code> and all * interactions with the <code>KeyedStack</code> require said key. * * @author Michael Pogran */ private class KeyedStack<K, V> { private HashMap<K, java.util.Stack<V>> stackMap = Maps.newHashMap(); public V push(V value, K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack == null) { stack = new java.util.Stack<V>(); this.stackMap.put(key, stack); } return stack.push(value); } public V peek(K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack != null) { return stack.peek(); } else { return null; } } public V pop(K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack != null) { return stack.pop(); } else { return null; } } public void clear() { stackMap = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); } }
/** @author Dennis Cosgrove */ public class PlusMinusOperation extends NumberPadOperation { private static java.util.Map<NumberModel<?>, PlusMinusOperation> map = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); public static synchronized PlusMinusOperation getInstance(NumberModel<?> model) { PlusMinusOperation rv = map.get(model); if (rv != null) { // pass } else { rv = new PlusMinusOperation(model); map.put(model, rv); } return rv; } private PlusMinusOperation(NumberModel<?> model) { super(java.util.UUID.fromString("6845e168-dfce-4f9e-b94f-d5674613f38c"), model); this.setName("\u00B1"); } @Override protected void perform(org.lgna.croquet.history.CompletionStep<?> step) { this.numberModel.negate(); step.finish(); } }
/** @author Dennis Cosgrove */ public class IntegerArithmeticExpressionRightOperandOnlyFillIn extends org.alice.ide.croquet.models.cascade.arithmetic .ArithmeticExpressionRightOperandOnlyFillIn { private static java.util.Map< org.lgna.project.ast.ArithmeticInfixExpression.Operator, IntegerArithmeticExpressionRightOperandOnlyFillIn> map = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); public static IntegerArithmeticExpressionRightOperandOnlyFillIn getInstance( org.lgna.project.ast.ArithmeticInfixExpression.Operator operator) { synchronized (map) { IntegerArithmeticExpressionRightOperandOnlyFillIn rv = map.get(operator); if (rv != null) { // pass } else { rv = new IntegerArithmeticExpressionRightOperandOnlyFillIn(operator); map.put(operator, rv); } return rv; } } private IntegerArithmeticExpressionRightOperandOnlyFillIn( org.lgna.project.ast.ArithmeticInfixExpression.Operator operator) { super( java.util.UUID.fromString("17a328e0-b763-4375-84f5-0a6a63e94964"), Integer.class, Integer.class, operator, Integer.class); } }
/** @author Dennis Cosgrove */ public class ProjectDocumentFrame extends org.lgna.croquet.PerspectiveDocumentFrame { public ProjectDocumentFrame( IdeConfiguration ideConfiguration, ApiConfigurationManager apiConfigurationManager) { this.apiConfigurationManager = apiConfigurationManager; this.noProjectPerspective = new org.alice.ide.perspectives.noproject.NoProjectPerspective(this); this.aliceMenuBar = new org.alice.ide.croquet.models.AliceMenuBar(this); this.codePerspective = new org.alice.stageide.perspectives.CodePerspective(this, aliceMenuBar); this.perspectiveState = new org.alice.stageide.perspectives.PerspectiveState(this.codePerspective); this.setupScenePerspective = new org.alice.stageide.perspectives.SetupScenePerspective(this, aliceMenuBar); this.metaDeclarationFauxState = new MetaDeclarationFauxState(this); this.instanceFactoryState = new org.alice.ide.instancefactory.croquet.InstanceFactoryState(this); this.findComposite = new org.alice.ide.croquet.models.project.find.croquet.FindComposite(this); this.uploadOperations = ideConfiguration != null ? ideConfiguration.createUploadOperations(this) : new org.lgna.croquet.Operation[0]; this.iconFactoryManager = apiConfigurationManager.createIconFactoryManager(); this.perspectiveState.addNewSchoolValueListener( new ValueListener<ProjectPerspective>() { @Override public void valueChanged(ValueEvent<ProjectPerspective> e) { ProjectApplication.getActiveInstance().updateTitle(); } }); } private static final javax.swing.KeyStroke CAPTURE_ENTIRE_WINDOW_KEY_STROKE = javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent.VK_F12, java.awt.event.InputEvent.SHIFT_MASK); private static final javax.swing.KeyStroke CAPTURE_ENTIRE_CONTENT_PANE_KEY_STROKE = javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent.VK_F12, java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK); private static final javax.swing.KeyStroke CAPTURE_RECTANGLE_KEY_STROKE = javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F12, 0); private void registerScreenCaptureKeyStrokes(org.lgna.croquet.views.AbstractWindow<?> window) { org.alice.ide.capture.ImageCaptureComposite imageCaptureComposite = org.alice.ide.capture.ImageCaptureComposite.getInstance(); window .getContentPane() .registerKeyboardAction( imageCaptureComposite .getCaptureEntireContentPaneOperation() .getImp() .getSwingModel() .getAction(), CAPTURE_ENTIRE_CONTENT_PANE_KEY_STROKE, org.lgna.croquet.views.SwingComponentView.Condition.WHEN_IN_FOCUSED_WINDOW); window .getContentPane() .registerKeyboardAction( imageCaptureComposite .getCaptureEntireWindowOperation() .getImp() .getSwingModel() .getAction(), CAPTURE_ENTIRE_WINDOW_KEY_STROKE, org.lgna.croquet.views.SwingComponentView.Condition.WHEN_IN_FOCUSED_WINDOW); if (window == this.getFrame()) { // pass } else { window .getContentPane() .registerKeyboardAction( imageCaptureComposite .getCaptureRectangleOperation() .getImp() .getSwingModel() .getAction(), CAPTURE_RECTANGLE_KEY_STROKE, org.lgna.croquet.views.SwingComponentView.Condition.WHEN_IN_FOCUSED_WINDOW); } } private void unregisterScreenCaptureKeyStrokes(org.lgna.croquet.views.AbstractWindow<?> window) { window.getContentPane().unregisterKeyboardAction(CAPTURE_ENTIRE_WINDOW_KEY_STROKE); window.getContentPane().unregisterKeyboardAction(CAPTURE_ENTIRE_CONTENT_PANE_KEY_STROKE); window.getContentPane().unregisterKeyboardAction(CAPTURE_RECTANGLE_KEY_STROKE); } /*package-private*/ void initialize() { this.registerScreenCaptureKeyStrokes(this.getFrame()); this.getInstanceFactoryState().addAndInvokeNewSchoolValueListener(this.instanceFactoryListener); org.alice.ide.croquet.models.ui.formatter.FormatterState.getInstance() .addNewSchoolValueListener(this.formatterListener); } @Override public void pushWindow(final org.lgna.croquet.views.AbstractWindow<?> window) { this.registerScreenCaptureKeyStrokes(window); super.pushWindow(window); } @Override public org.lgna.croquet.views.AbstractWindow<?> popWindow() { org.lgna.croquet.views.AbstractWindow<?> window = super.popWindow(); this.unregisterScreenCaptureKeyStrokes(window); return window; } public void disableRendering( org.alice.ide.ReasonToDisableSomeAmountOfRendering reasonToDisableSomeAmountOfRendering) { this.stack.push(reasonToDisableSomeAmountOfRendering); org.alice.stageide.sceneeditor.StorytellingSceneEditor.getInstance() .disableRendering(reasonToDisableSomeAmountOfRendering); } public void enableRendering() { if (this.stack.isEmpty()) { edu.cmu.cs.dennisc.java.util.logging.Logger.severe(this); } else { org.alice.ide.ReasonToDisableSomeAmountOfRendering reasonToDisableSomeAmountOfRendering = this.stack.pop(); org.alice.stageide.sceneeditor.StorytellingSceneEditor.getInstance() .enableRendering(reasonToDisableSomeAmountOfRendering); } } @Override public ProjectDocument getDocument() { return org.alice.ide.project.ProjectDocumentState.getInstance().getValue(); } public ApiConfigurationManager getApiConfigurationManager() { return this.apiConfigurationManager; } public org.lgna.croquet.Operation[] getUploadOperations() { return this.uploadOperations; } public org.alice.ide.instancefactory.croquet.InstanceFactoryState getInstanceFactoryState() { return this.instanceFactoryState; } public MetaDeclarationFauxState getMetaDeclarationFauxState() { return this.metaDeclarationFauxState; } public org.alice.ide.perspectives.noproject.NoProjectPerspective getNoProjectPerspective() { return this.noProjectPerspective; } public org.alice.stageide.perspectives.CodePerspective getCodePerspective() { return this.codePerspective; } public org.alice.stageide.perspectives.SetupScenePerspective getSetupScenePerspective() { return this.setupScenePerspective; } public org.lgna.croquet.ItemState<org.alice.ide.perspectives.ProjectPerspective> getPerspectiveState() { return this.perspectiveState; } @Override public void setPerspective(Perspective perspective) { super.setPerspective(perspective); // sigh, the listener to perspective state should be enough, but not all perspectives // are changed through the state... sigh... then what's the point!? ProjectApplication.getActiveInstance().updateTitle(); } public boolean isInCodePerspective() { return this.getPerspectiveState().getValue() == this.getCodePerspective(); } public boolean isNoCodePerspective() { return (this.getPerspective() instanceof NoProjectPerspective); } public boolean isInSetupScenePerspective() { return this.getPerspectiveState().getValue() == this.getSetupScenePerspective(); } public org.lgna.croquet.Operation getSetToCodePerspectiveOperation() { return this.getPerspectiveState().getItemSelectionOperation(this.getCodePerspective()); } public org.lgna.croquet.Operation getSetToSetupScenePerspectiveOperation() { return this.getPerspectiveState().getItemSelectionOperation(this.getSetupScenePerspective()); } public void setToCodePerspectiveTransactionlessly() { this.getPerspectiveState().setValueTransactionlessly(this.getCodePerspective()); } public void setToSetupScenePerspectiveTransactionlessly() { this.getPerspectiveState().setValueTransactionlessly(this.getSetupScenePerspective()); } public org.alice.ide.croquet.models.project.find.croquet.FindComposite getFindComposite() { return this.findComposite; } public org.alice.ide.croquet.models.AliceMenuBar getAliceMenuBar() { return this.aliceMenuBar; } public org.lgna.croquet.meta.MetaState<org.lgna.project.ast.NamedUserType> getTypeMetaState() { if (this.typeMetaState != null) { // pass } else { org.alice.ide.declarationseditor.DeclarationTabState declarationTabState = this.declarationsEditorComposite.getTabState(); this.typeMetaState = new org.lgna.croquet.meta.StateTrackingMetaState< org.lgna.project.ast.NamedUserType, DeclarationComposite<?, ?>>(declarationTabState) { @Override protected org.lgna.project.ast.NamedUserType getValue( org.lgna.croquet.State<org.alice.ide.declarationseditor.DeclarationComposite<?, ?>> state) { DeclarationComposite<?, ?> declarationComposite = state.getValue(); if (declarationComposite != null) { return edu.cmu.cs.dennisc.java.lang.ClassUtilities.getInstance( declarationComposite.getType(), org.lgna.project.ast.NamedUserType.class); } else { return null; } } }; } return this.typeMetaState; } public org.alice.ide.iconfactory.IconFactoryManager getIconFactoryManager() { return this.iconFactoryManager; } public org.alice.ide.declarationseditor.DeclarationsEditorComposite getDeclarationsEditorComposite() { return this.declarationsEditorComposite; } public org.lgna.croquet.Operation getResourcesDialogLaunchOperation() { return this.resourcesDialogLaunchOperation; } public org.lgna.croquet.BooleanState getStasticsFrameIsShowingState() { return this.stasticsFrameIsShowingState; } private static final Integer HIGHLIGHT_STENCIL_LAYER = javax.swing.JLayeredPane.POPUP_LAYER - 2; @Deprecated public org.alice.ide.highlight.IdeHighlightStencil getHighlightStencil() { if (this.highlightStencil != null) { // pass } else { this.highlightStencil = new org.alice.ide.highlight.IdeHighlightStencil(this.getFrame(), HIGHLIGHT_STENCIL_LAYER); } return this.highlightStencil; } // <lg> @Deprecated public void showHighlightStencil( final org.lgna.croquet.views.TrackableShape trackableShape, String noteText) { org.alice.ide.highlight.IdeHighlightStencil highlightStencil = this.getHighlightStencil(); highlightStencil.showHighlightOverTrackableShape(trackableShape, noteText); } // </lg> public org.lgna.project.ast.AbstractCode getFocusedCode() { org.lgna.project.ast.AbstractDeclaration declaration = this.getMetaDeclarationFauxState().getValue(); if (declaration instanceof org.lgna.project.ast.AbstractCode) { return (org.lgna.project.ast.AbstractCode) declaration; } else { return null; } } public void setFocusedCode(org.lgna.project.ast.AbstractCode nextFocusedCode) { this.selectDeclaration(nextFocusedCode); } public void selectDeclarationComposite( org.alice.ide.declarationseditor.DeclarationComposite declarationComposite) { if (declarationComposite != null) { org.lgna.project.ast.AbstractDeclaration declaration = declarationComposite.getDeclaration(); // org.lgna.project.ast.AbstractType<?, ?, ?> type; // if( declaration instanceof org.lgna.project.ast.AbstractType<?, ?, ?> ) { // type = (org.lgna.project.ast.AbstractType<?, ?, ?>)declaration; // } else if( declaration instanceof org.lgna.project.ast.AbstractCode ) { // org.lgna.project.ast.AbstractCode code = (org.lgna.project.ast.AbstractCode)declaration; // type = code.getDeclaringType(); // } else { // type = null; // } // if( type instanceof org.lgna.project.ast.NamedUserType ) { // org.alice.ide.declarationseditor.TypeState.getInstance().setValueTransactionlessly( // (org.lgna.project.ast.NamedUserType)type ); // } org.alice.ide.declarationseditor.DeclarationTabState tabState = this.getDeclarationsEditorComposite().getTabState(); // if( tabState.containsItem( declarationComposite ) ) { // //pass // } else { // tabState.addItem( declarationComposite ); // } tabState.setValueTransactionlessly(declarationComposite); } } private void selectDeclaration(org.lgna.project.ast.AbstractDeclaration declaration) { this.selectDeclarationComposite( org.alice.ide.declarationseditor.DeclarationComposite.getInstance(declaration)); } public org.lgna.croquet.Operation getNewProjectOperation() { return this.newProjectOperation; } public org.lgna.croquet.Operation getOpenProjectOperation() { return this.openProjectOperation; } public org.lgna.croquet.Operation getUndoOperation() { return this.undoOperation; } public org.lgna.croquet.Operation getRedoOperation() { return this.redoOperation; } private final ApiConfigurationManager apiConfigurationManager; private org.lgna.croquet.meta.MetaState<org.lgna.project.ast.NamedUserType> typeMetaState; private final org.lgna.croquet.Operation[] uploadOperations; private final org.alice.ide.croquet.models.project.find.croquet.FindComposite findComposite; private final org.alice.ide.perspectives.noproject.NoProjectPerspective noProjectPerspective; private final org.alice.stageide.perspectives.CodePerspective codePerspective; private final org.alice.stageide.perspectives.SetupScenePerspective setupScenePerspective; private final org.alice.ide.croquet.models.AliceMenuBar aliceMenuBar; private final org.alice.stageide.perspectives.PerspectiveState perspectiveState; private final MetaDeclarationFauxState metaDeclarationFauxState; private final org.alice.ide.instancefactory.croquet.InstanceFactoryState instanceFactoryState; private final org.alice.ide.iconfactory.IconFactoryManager iconFactoryManager; private final org.alice.ide.declarationseditor.DeclarationsEditorComposite declarationsEditorComposite = new org.alice.ide.declarationseditor.DeclarationsEditorComposite(); private final org.lgna.croquet.Operation resourcesDialogLaunchOperation = org.lgna.croquet.imp.launch.LazySimpleLaunchOperationFactory.createInstance( org.alice.ide.resource.manager.ResourceManagerComposite.class, new edu.cmu.cs.dennisc.pattern.Lazy< org.alice.ide.resource.manager.ResourceManagerComposite>() { @Override protected org.alice.ide.resource.manager.ResourceManagerComposite create() { return new org.alice.ide.resource.manager.ResourceManagerComposite( ProjectDocumentFrame.this); } }, org.lgna.croquet.Application.DOCUMENT_UI_GROUP) .getLaunchOperation(); private final org.lgna.croquet.BooleanState stasticsFrameIsShowingState = org.lgna.croquet.imp.frame.LazyIsFrameShowingState.createInstance( org.lgna.croquet.Application.INFORMATION_GROUP, org.alice.ide.croquet.models.project.stats.croquet.StatisticsFrameComposite.class, new edu.cmu.cs.dennisc.pattern.Lazy< org.alice.ide.croquet.models.project.stats.croquet.StatisticsFrameComposite>() { @Override protected org.alice.ide.croquet.models.project.stats.croquet.StatisticsFrameComposite create() { return new org.alice.ide.croquet.models.project.stats.croquet .StatisticsFrameComposite(ProjectDocumentFrame.this); } }); private final edu.cmu.cs.dennisc.java.util.DStack< org.alice.ide.ReasonToDisableSomeAmountOfRendering> stack = edu.cmu.cs.dennisc.java.util.Stacks.newStack(); private final java.util.Map< org.lgna.project.ast.AbstractCode, org.alice.ide.instancefactory.InstanceFactory> mapCodeToInstanceFactory = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); private final org.lgna.croquet.event.ValueListener<org.alice.ide.instancefactory.InstanceFactory> instanceFactoryListener = new org.lgna.croquet.event.ValueListener< org.alice.ide.instancefactory.InstanceFactory>() { @Override public void valueChanged( org.lgna.croquet.event.ValueEvent<org.alice.ide.instancefactory.InstanceFactory> e) { org.alice.ide.instancefactory.InstanceFactory nextValue = e.getNextValue(); if (nextValue != null) { org.lgna.project.ast.AbstractCode code = getFocusedCode(); if (code != null) { mapCodeToInstanceFactory.put(code, nextValue); } } } }; private final org.lgna.croquet.event.ValueListener<org.alice.ide.formatter.Formatter> formatterListener = new org.lgna.croquet.event.ValueListener<org.alice.ide.formatter.Formatter>() { @Override public void valueChanged( org.lgna.croquet.event.ValueEvent<org.alice.ide.formatter.Formatter> e) { edu.cmu.cs.dennisc.java.awt.ComponentUtilities.revalidateTree( getFrame().getAwtComponent()); } }; private org.alice.ide.highlight.IdeHighlightStencil highlightStencil; private final org.lgna.croquet.Operation newProjectOperation = new org.alice.ide.croquet.models.projecturi.NewProjectOperation(this); private final org.lgna.croquet.Operation openProjectOperation = new org.alice.ide.croquet.models.projecturi.OpenProjectOperation(this); private final org.lgna.croquet.Operation undoOperation = new org.alice.ide.croquet.models.history.UndoOperation(this); private final org.lgna.croquet.Operation redoOperation = new org.alice.ide.croquet.models.history.RedoOperation(this); }
/** * An object that receives <code>VMObserver</code> events from the <code>VMObserverManager</code>, * processes these events, creates the appropriate <code>EventNode</code>, and then notifies any * listeners of statement execution. * * @author Paul Gross */ public class VMExecutionObserver implements VMObserver { private boolean isRecording = false; private boolean hasInvokedEntryPoint = false; private final Map<Object, UserField> instanceMap = Maps.newHashMap(); private final Set<CurrentExecutionListener> executionListeners = Sets.newHashSet(); private final java.util.Map<Statement, java.util.ArrayList<AbstractEventNode<?>>> statementEventNodes = Maps.newHashMap(); private final java.util.List<LambdaEventNode> lambdaEventNodes = Lists.newLinkedList(); private final KeyedStack<ComponentThread, AbstractEventNode<?>> eventNodeStack = new KeyedStack<ComponentThread, AbstractEventNode<?>>(); private AbstractEventNode<?> rootEventNode; private UserInstance sceneInstance; public VMExecutionObserver(MessagingVirtualMachine virtualMachine) { virtualMachine.addObserver(this); } public void addCurrentExecutionListener(CurrentExecutionListener listener) { synchronized (this.executionListeners) { this.executionListeners.add(listener); } } public boolean removeCurrentExecutionListener(CurrentExecutionListener listener) { synchronized (this.executionListeners) { return this.executionListeners.remove(listener); } } public UserInstance getSceneInstance() { return this.sceneInstance; } public boolean eventNodesExistForStatement(Statement statement) { java.util.Collection<AbstractEventNode<?>> nodes = this.statementEventNodes.get(statement); return (nodes != null) && (nodes.size() > 0); } public java.util.ArrayList<AbstractEventNode<?>> getEventNodesForStatement(Statement statement) { return this.statementEventNodes.get(statement); } public AbstractEventNode<?> getEventNodeForStatementAtTime(Statement statement, double time) { for (AbstractEventNode<?> event : getEventNodesForStatement(statement)) { if (event.isExecutingAtTime(time)) { return event; } } return null; } public boolean isRootEventNode(AbstractEventNode<?> eventNode) { return (eventNode == this.rootEventNode); } public AbstractEventNode<?> getRootEventNode() { return this.rootEventNode; } public java.util.List<LambdaEventNode> getLambdaEventNodes() { return this.lambdaEventNodes; } public Map<Object, UserField> getInstanceMap() { return this.instanceMap; } public boolean hasInvokedEntryPoint() { return this.hasInvokedEntryPoint; } public boolean isRecording() { return this.isRecording; } public void setIsRecording(boolean value) { this.isRecording = value; } /** * Called when a new {@link VMObservableEvent} is passed. Executes the correct method based on the * {@link VMMessage} for the event. * * @param event {@link VMObservableEvent} passed from {@link VMObserverManager} */ @Override public synchronized void update(VMObservableEvent event) { VMMessage eventMsg = event.getVMMessage(); if (eventMsg == VMMessage.START_RECORDING) { this.isRecording = true; } else if (eventMsg == VMMessage.STOP_RECORDING) { this.isRecording = false; } else if (eventMsg == VMMessage.CREATE_INSTANCE) { if ((event.getProperties().length == 1) && (event.getProperties()[0] instanceof UserField)) { UserField field = (UserField) event.getProperties()[0]; Object instance = event.getObject(); if (instance instanceof UserInstance) { if (((UserInstance) instance).getType().isAssignableTo(SScene.class)) { this.sceneInstance = (UserInstance) instance; } instance = ((UserInstance) instance).getJavaInstance(); } this.instanceMap.put(instance, field); } } // Lambda invocations come from eventListeners and are // recorded outside the default record loop if (eventMsg == VMMessage.START_LAMBDA_INVOKE) { if (event.getObject() instanceof UserLambda) { startLambdaInvocation(event); } else { throw new ExecutionObserverException(event); } } else if (eventMsg == VMMessage.END_LAMBDA_INVOKE) { if (event.getObject() instanceof UserLambda) { endLambdaInvocation(event); } else { throw new ExecutionObserverException(event); } } // Should we record this message? boolean shouldRecord = isRecording(); if (!shouldRecord) { if (event.getThread() != null) { shouldRecord = event.getThread().getDescription().contentEquals("eventThread"); } } synchronized (this) { if (shouldRecord) { switch (eventMsg) { case RESET: reset(); break; case START_INVOKE_ENTRY_POINT: this.hasInvokedEntryPoint = true; break; case START_EXP_EVAL: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof Expression) { // Non-function method invocations are handled separately if (event.getObject() instanceof MethodInvocation) { MethodInvocation methodInvocation = (MethodInvocation) event.getObject(); if (methodInvocation.method.getValue().isFunction()) { startExpressionEvaluation(event); } } else { startExpressionEvaluation(event); } } else { throw new ExecutionObserverException(event); } } break; case END_EXP_EVAL: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof Expression) { // Non-function method invocations are handled separately if (event.getObject() instanceof MethodInvocation) { MethodInvocation methodInvocation = (MethodInvocation) event.getObject(); if (methodInvocation.method.getValue().isFunction()) { endExpressionEvaluation(event); } } else { endExpressionEvaluation(event); } } else { throw new ExecutionObserverException(event); } } break; case START_METHOD_INVOKE: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof MethodInvocation) { startMethodInvocation(event); } else { throw new ExecutionObserverException(event); } } break; case START_STMT_EXEC: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof BlockStatement) { // pass // } else if( event.getObject() instanceof Comment ) { // //pass // } else { } else { startStatement(event); } } break; case END_STMT_EXEC: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof BlockStatement) { // //pass // } else if( event.getObject() instanceof Comment ) { // //pass // } else { } else { endStatement(event); } } break; case START_CONTAINER: if (this.hasInvokedEntryPoint) { if ((event.getObject() instanceof AbstractStatementWithBody) || (event.getObject() instanceof BlockStatement)) { startContainer(event); } else { throw new ExecutionObserverException(event); } } break; case END_CONTAINER: if (this.hasInvokedEntryPoint) { if ((event.getObject() instanceof AbstractStatementWithBody) || (event.getObject() instanceof BlockStatement)) { endContainer(event); } else { throw new ExecutionObserverException(event); } } break; } } } } private void startLambdaInvocation(VMObservableEvent event) { org.lgna.project.ast.UserLambda lambda = (UserLambda) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); org.lgna.project.ast.AbstractMethod method = (AbstractMethod) event.getProperties()[0]; // We ignore scene activation if (!method.getName().contentEquals("sceneActivated")) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(lambda, thread, startTime, null); ((LambdaEventNode) eventNode).setInvokingEventMethod(method); pushEventNode(eventNode, false); } } private void endLambdaInvocation(VMObservableEvent event) { org.lgna.project.ast.UserLambda lambda = (UserLambda) event.getObject(); org.lgna.project.ast.AbstractMethod method = (AbstractMethod) event.getProperties()[0]; ComponentThread thread = event.getThread(); double endTime = event.getTime(); if (!method.getName().contentEquals("sceneActivated")) { AbstractEventNode<?> eventNode = popEventNode(thread, false); lambdaEventNodes.add((LambdaEventNode) eventNode); if ((eventNode != null) && (eventNode.getAstNode() == lambda) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } } /** * Handles the beginning of evaluation of an {@link Expression}. * * @param event VMObservableEvent event for expression */ private void startExpressionEvaluation(VMObservableEvent event) { Expression expression = (Expression) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); AbstractEventNode<?> parentNode = peekEventNode(thread); ExpressionEvaluationEventNode eventNode = (ExpressionEvaluationEventNode) EventNodeFactory.createEventNode(expression, thread, startTime, parentNode); // Add expression evaluation to ExpressionStatementEventNode if (parentNode instanceof ExpressionStatementEventNode) { ((ExpressionStatementEventNode) parentNode).addExpressionEvaluationNode(eventNode); } // Handle expression evaluation for ConditionalEventNode else if (parentNode instanceof ConditionalStatementEventNode) { ((ConditionalStatementEventNode) parentNode).addConditionalEvaluation(eventNode); } // Handle expression evaluation for CountLoopEventNode else if (parentNode instanceof CountLoopEventNode) { ((CountLoopEventNode) parentNode).setCountExpressionNode(eventNode); } // Handle expression evaluation for EachInArrayTogetherEventNode else if (parentNode instanceof EachInArrayTogetherEventNode) { ((EachInArrayTogetherEventNode) parentNode).setArrayExpressionNode(eventNode); } // Handle expression evaluation for ForEachInArrayLoopEventNode else if (parentNode instanceof ForEachInArrayLoopEventNode) { ((ForEachInArrayLoopEventNode) parentNode).setArrayExpressionNode(eventNode); } // Handle expression evaluation for WhileLoopEventNode else if (parentNode instanceof WhileLoopEventNode) { ((WhileLoopEventNode) parentNode).addConditionalEvaluation(eventNode); } // Handle expression evaluation for LocalDeclarationStatementEventNode else if (parentNode instanceof LocalDeclarationStatementEventNode) { ((LocalDeclarationStatementEventNode) parentNode).setInitializerExpression(eventNode); } // Handle expression evaluation for ReturnStatementEventNode else if (parentNode instanceof ReturnStatementEventNode) { ((ReturnStatementEventNode) parentNode).setExpressionNode(eventNode); } // Handle expression evaluation for ExpressionEvaluationEventNode else if (parentNode instanceof ExpressionEvaluationEventNode) { // pass - handled on endExpressionEvaluation } else { throw new ExecutionObserverException("Parent node invalid:" + parentNode.toString(), event); } pushEventNode(eventNode, false); } /** * Handles the ending of evaluation of an {@link Expression}. * * @param event VMObservableEvent event for expression */ private void endExpressionEvaluation(VMObservableEvent event) { Expression expression = (Expression) event.getObject(); ComponentThread thread = event.getThread(); double endTime = event.getTime(); Object value = event.getProperties()[0]; AbstractEventNode<?> eventNode = popEventNode(thread, false); if ((eventNode != null) && (eventNode.getAstNode() == expression) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); ((ExpressionEvaluationEventNode) eventNode).setValue(value); UserField field = this.getUserFieldForInstance(value); if (field != null) { ((ExpressionEvaluationEventNode) eventNode).setValueField(field); } } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } /** * Handles beginning execution of a {@link Statement}. * * @param event {@link VMObservableEvent} event for statement */ private void startStatement(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); AbstractEventNode<?> parentNode = peekEventNode(getThreadForNode(statement, thread)); // A Statement should always have a parent node (which can only be a ContainerEventNode) if (parentNode instanceof ContainerEventNode) { ContainerEventNode<?> containerNode = (ContainerEventNode<?>) parentNode; AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, containerNode); pushEventNode(eventNode, false); } else { throw new ExecutionObserverException("Parent node invalid: " + parentNode.toString(), event); } } /** * Handles ending execution of a {@link Statement}. * * @param event {@link VMObservableEvent} event for statement */ private void endStatement(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double endTime = event.getTime(); AbstractEventNode<?> eventNode = popEventNode(thread, true); if ((eventNode != null) && (eventNode.getAstNode() == statement) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } /** * Handles beginning execution of container statement ( {@link AbstractStatementWithBody} or * {@link BlockStatement}). * * @param event {@link VMObservableEvent} event for container type statement */ private void startContainer(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); AbstractEventNode<?> parentNode = peekEventNode(getThreadForNode(statement, thread)); // Root case if (parentNode == null) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, null); this.rootEventNode = eventNode; pushEventNode(eventNode, true); } else if (parentNode instanceof ConditionalStatementEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); pushEventNode(eventNode, true); } else if (parentNode instanceof ContainerEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); pushEventNode(eventNode, true); } else if (parentNode instanceof ExpressionStatementEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); ((ExpressionStatementEventNode) parentNode) .addUserMethodEventNode((ContainerEventNode<?>) eventNode); pushEventNode(eventNode, true); } else if (parentNode instanceof ExpressionEvaluationEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); pushEventNode(eventNode, true); } else if (parentNode instanceof LambdaEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); ((LambdaEventNode) parentNode).addBodyEventNode((ContainerEventNode<?>) eventNode); pushEventNode(eventNode, true); } else { throw new ExecutionObserverException("Parent node invalid: " + parentNode.toString(), event); } } /** * Handles ending execution of Container statement ( {@link AbstractStatementWithBody} or {@link * BlockStatement}). * * @param event {@link VMObservableEvent} event for container type statement */ private void endContainer(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double endTime = event.getTime(); AbstractEventNode<?> eventNode = popEventNode(thread, true); if ((eventNode != null) && (eventNode.getAstNode() == statement) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } /** * Handles beginning execution of {@link MethodInvocation}. * * @param event {@link VMObservableEvent} event for invocation */ private void startMethodInvocation(VMObservableEvent event) { MethodInvocation invocation = (MethodInvocation) event.getObject(); ComponentThread thread = event.getThread(); Object instance = event.getProperties()[1]; UserField field = getUserFieldForInstance(instance); AbstractEventNode<?> parentNode = peekEventNode(getThreadForNode(invocation, thread)); // Add instance and referencing field to parent node if (parentNode instanceof ExpressionStatementEventNode) { ExpressionStatementEventNode statementNode = (ExpressionStatementEventNode) parentNode; if ((instance != null) & (field != null)) { statementNode.setCallerInstance(instance); statementNode.setCallerField(field); } if ((instance != null) & (field != null)) { notifyListenersOfStart(statementNode); // Now that caller has been set, notify listeners } if (invocation.method.getValue() instanceof UserMethod) { UserMethod userMethod = (UserMethod) invocation.method.getValue(); if (!userMethod.isFunction()) { statementNode.setUserMethod(userMethod); } } } else if (parentNode instanceof ExpressionEvaluationEventNode) { if (field != null) { ((ExpressionEvaluationEventNode) parentNode).setValueField(field); } } } /** * Clears all maps involved in tracking. Note: this method does <i>not</i> remove <code> * CurrentExecutionListeners</code>. */ private void reset() { statementEventNodes.clear(); eventNodeStack.clear(); } /** * Pushes an {@link AbstractEventNode<?>} onto the stack and executes associated functions. * * @param eventNode <code>AbstractEventNode<?></code> to push onto the stack * @param shouldNotify boolean dictating whether listeners should be notified of push */ private void pushEventNode(AbstractEventNode<?> eventNode, boolean shouldNotify) { ArrayList<AbstractEventNode<?>> eventNodes = this.statementEventNodes.get(eventNode.getAstNode()); if (eventNodes == null) { eventNodes = new ArrayList<AbstractEventNode<?>>(); if (eventNode.getAstNode() instanceof Statement) { this.statementEventNodes.put((Statement) eventNode.getAstNode(), eventNodes); } } eventNodes.add(eventNode); this.eventNodeStack.push(eventNode, eventNode.getThread()); if (shouldNotify) { notifyListenersOfStart(eventNode); } } /** * Peeks {@link AbstractEventNode<?>} from top of stack for given thread. * * @param thread {@link ComponentThread} to check stack for * @return AbstractEventNode<?> on top of stack */ private AbstractEventNode<?> peekEventNode(ComponentThread thread) { return this.eventNodeStack.peek(thread); } /** * Removes and returns {@link AbstractEventNode<?>} from top of stack for a given thread. * * @param thread {@link ComponentThread} to remove stack for * @return <code>AbstractEventNode<?></code> removed from stack */ private AbstractEventNode<?> popEventNode(ComponentThread thread, boolean shouldNotify) { AbstractEventNode<?> rv = this.eventNodeStack.pop(thread); if (shouldNotify) { notifyListenersOfEnd(rv); } return rv; } /** * Gets the correct thread for lookup in {@link KeyedStack}. In the instance of parallel execution * (<code>DoTogether</code> and <code>EachInArrayTogether</code> statements) we want to get the * parent thread. * * @param astNode {@link Node} in AST to check * @param thread {@link ComponentThread} to reference * @return the correct <code>ComponentThread</code> for lookup */ private ComponentThread getThreadForNode(Node astNode, ComponentThread thread) { if (astNode.getParent() instanceof BlockStatement) { BlockStatement blockStatement = (BlockStatement) astNode.getParent(); if (blockStatement.getParent() instanceof DoTogether) { DoTogether doTogether = (DoTogether) blockStatement.getParent(); // special case for DoTogether with only one statement if (doTogether.body.getValue().statements.size() > 1) { return thread.getParentThread(); } else { return thread; } } else { return thread; } } else if (astNode.getParent() instanceof EachInArrayTogether) { return thread.getParentThread(); } else { return thread; } } private void notifyListenersOfStart(AbstractEventNode<?> eventNode) { synchronized (this.executionListeners) { for (CurrentExecutionListener listener : this.executionListeners) { listener.startingExecution(eventNode); } } } private void notifyListenersOfEnd(AbstractEventNode<?> eventNode) { synchronized (this.executionListeners) { for (CurrentExecutionListener listener : this.executionListeners) { listener.endingExecution(eventNode); } } } /** * Based on provided <code>Object</code>, finds the applicable field set during instance creation. * * @param caller object evaluated by vm * @return mapped <code>UserField</code> for value */ private UserField getUserFieldForInstance(Object instance) { if (instance instanceof UserInstance) { instance = ((UserInstance) instance).getJavaInstance(); } // Get instance from invocation - special case for joints else if (instance instanceof org.lgna.story.SJoint) { org.lgna.story.SJoint joint = (org.lgna.story.SJoint) instance; org.lgna.story.implementation.JointImp jointImp = org.lgna.story.EmployeesOnly.getImplementation(joint); org.lgna.story.implementation.JointedModelImp<?, ?> jointedModelImp = jointImp.getJointedModelParent(); org.lgna.story.SJointedModel jointedModel = jointedModelImp.getAbstraction(); instance = jointedModel; } return this.instanceMap.get(instance); } /** * Specialized stack-like structure that allows for multiple stacks based on a key. Each key * passed into the <code>KeyedStack</code> is given a unique <code>Stack</code> and all * interactions with the <code>KeyedStack</code> require said key. * * @author Michael Pogran */ private class KeyedStack<K, V> { private HashMap<K, java.util.Stack<V>> stackMap = Maps.newHashMap(); public V push(V value, K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack == null) { stack = new java.util.Stack<V>(); this.stackMap.put(key, stack); } return stack.push(value); } public V peek(K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack != null) { return stack.peek(); } else { return null; } } public V pop(K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack != null) { return stack.pop(); } else { return null; } } public void clear() { stackMap = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); } } }
public void clear() { stackMap = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); }
/** @author Dennis Cosgrove */ public class Decoder { private static class ClassReflectionProxyAndMethodName { private final ClassReflectionProxy classReflectionProxy; private final String name; public ClassReflectionProxyAndMethodName( ClassReflectionProxy classReflectionProxy, String name) { this.classReflectionProxy = classReflectionProxy; this.name = name; } public ClassReflectionProxy getClassReflectionProxy() { return this.classReflectionProxy; } public String getName() { return this.name; } } private static final edu.cmu.cs.dennisc.map.MapToMap< ClassReflectionProxy, String, ClassReflectionProxyAndMethodName> betweenClassesMethodMap = edu.cmu.cs.dennisc.map.MapToMap.newInstance(); private static final edu.cmu.cs.dennisc.map.MapToMap<ClassReflectionProxy, String, String> intraClassMethodMap = edu.cmu.cs.dennisc.map.MapToMap.newInstance(); private static final java.util.Map<String, String> mapClassNameToClassName = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); public static void addMethodFilterWithinClass( ClassReflectionProxy classReflectionProxy, String prevName, String nextName) { Decoder.intraClassMethodMap.put(classReflectionProxy, prevName, nextName); } public static void addMethodFilterWithinClass(Class<?> cls, String prevName, String nextName) { addMethodFilterWithinClass( JavaType.getInstance(cls).getClassReflectionProxy(), prevName, nextName); } public static void addMethodFilterBetweenClasses( ClassReflectionProxy prevClassReflectionProxy, String prevName, ClassReflectionProxy nextClassReflectionProxy, String nextName) { Decoder.betweenClassesMethodMap.put( prevClassReflectionProxy, prevName, new ClassReflectionProxyAndMethodName(nextClassReflectionProxy, nextName)); } public static void addMethodFilterBetweenClasses( Class<?> prevCls, String prevName, Class<?> nextCls, String nextName) { addMethodFilterBetweenClasses( JavaType.getInstance(prevCls).getClassReflectionProxy(), prevName, JavaType.getInstance(nextCls).getClassReflectionProxy(), nextName); } public static void addClassFilter( ClassReflectionProxy prevClassReflectionProxy, ClassReflectionProxy nextClassReflectionProxy) { Decoder.mapClassNameToClassName.put( prevClassReflectionProxy.getName(), nextClassReflectionProxy.getName()); } public static void addClassFilter( ClassReflectionProxy prevClassReflectionProxy, Class<?> nextCls) { addClassFilter( prevClassReflectionProxy, JavaType.getInstance(nextCls).getClassReflectionProxy()); } public static void addClassFilter(Class<?> prevCls, Class<?> nextCls) { addClassFilter( JavaType.getInstance(prevCls).getClassReflectionProxy(), JavaType.getInstance(nextCls).getClassReflectionProxy()); } private static String filterClassNameIfNecessary(String clsName) { String rv = Decoder.mapClassNameToClassName.get(clsName); if (rv != null) { // pass } else { rv = clsName; } return rv; } // private static String filterMethodNameIfNecessary( ClassReflectionProxy classReflectionProxy, // String name ) { // String rv = Decoder.intraClassMethodMap.get( classReflectionProxy, name ); // if( rv != null ) { // //pass // } else { // rv = name; // } // return rv; // } public Decoder( org.lgna.project.Version srcVersion, org.lgna.project.Version dstVersion, DecodeIdPolicy policy) { this.srcVersion = srcVersion; this.dstVersion = dstVersion; this.policy = policy; } private static ClassReflectionProxy createClassReflectionProxy(String clsName) { return new ClassReflectionProxy(filterClassNameIfNecessary(clsName)); } private String getClassName(org.w3c.dom.Element xmlElement) { String rv = xmlElement.getAttribute(CodecConstants.TYPE_ATTRIBUTE); return rv; } private ClassReflectionProxy getJavaClassInfo(org.w3c.dom.Element xmlElement) { return createClassReflectionProxy(getClassName(xmlElement)); } // todo: investigate private Class<?> getCls(org.w3c.dom.Element xmlElement) { return edu.cmu.cs.dennisc.java.lang.reflect.ReflectionUtilities.getClassForName( getClassName(xmlElement)); } // todo: investigate private Object newInstance(org.w3c.dom.Element xmlElement) { return edu.cmu.cs.dennisc.java.lang.reflect.ReflectionUtilities.newInstance( getClassName(xmlElement)); } public Object decodeValue( org.w3c.dom.Element xmlValue, java.util.Map<Integer, AbstractDeclaration> map) { Object rv; if (xmlValue.hasAttribute("isNull")) { rv = null; } else { String tagName = xmlValue.getTagName(); if (tagName.equals("node")) { try { rv = decode(xmlValue, map); } catch (RuntimeException re) { re.printStackTrace(); // rv = new NullLiteral(); rv = null; } } else if (tagName.equals("collection")) { java.util.Collection collection = (java.util.Collection) newInstance(xmlValue); org.w3c.dom.NodeList nodeList = xmlValue.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { org.w3c.dom.Element xmlItem = (org.w3c.dom.Element) nodeList.item(i); collection.add(decodeValue(xmlItem, map)); } rv = collection; // } else if( tagName.equals( "resource" ) ) { // String uuidText = xmlValue.getAttribute( CodecConstants.UUID_ATTRIBUTE ); // edu.cmu.cs.dennisc.print.PrintUtilities.println( "uuidText", uuidText ); // java.util.UUID uuid = java.util.UUID.fromString( uuidText ); // edu.cmu.cs.dennisc.print.PrintUtilities.println( "uuid", uuid ); // rv = org.alice.virtualmachine.Resource.get( uuid ); } else if (tagName.equals("value")) { Class<?> cls = getCls(xmlValue); String textContent = xmlValue.getTextContent(); if (cls.equals(String.class)) { rv = textContent; } else { try { rv = edu.cmu.cs.dennisc.java.lang.reflect.ReflectionUtilities.valueOf(cls, textContent); } catch (RuntimeException re) { if ("DIVIDE".equals(textContent)) { rv = edu.cmu.cs.dennisc.java.lang.reflect.ReflectionUtilities.valueOf( cls, "REAL_DIVIDE"); } else if ("REMAINDER".equals(textContent)) { rv = edu.cmu.cs.dennisc.java.lang.reflect.ReflectionUtilities.valueOf( cls, "REAL_REMAINDER"); } else { throw re; } } } } else { throw new RuntimeException(); } } return rv; } private ClassReflectionProxy decodeType(org.w3c.dom.Element xmlElement, String nodeName) { org.w3c.dom.Element xmlClass = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName(xmlElement, nodeName); String clsName = xmlClass.getAttribute("name"); return createClassReflectionProxy(clsName); } private UserArrayType decodeUserArrayType( org.w3c.dom.Element xmlElement, java.util.Map<Integer, AbstractDeclaration> map) { org.w3c.dom.Element xmlLeafType = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName(xmlElement, "leafType"); org.w3c.dom.Element xmlDimensionCount = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName( xmlElement, "dimensionCount"); org.w3c.dom.Element xmlLeafTypeNode = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName(xmlLeafType, "node"); org.w3c.dom.Node xmlLeafTypeFirstChild = xmlLeafType.getFirstChild(); if (xmlLeafTypeFirstChild instanceof org.w3c.dom.Element) { org.w3c.dom.Element xmlLeafTypeFirstChildElement = (org.w3c.dom.Element) xmlLeafTypeFirstChild; if (xmlLeafTypeFirstChildElement.hasAttribute(CodecConstants.UNIQUE_KEY_ATTRIBUTE)) { int arrayTypeUniqueKey = getUniqueKey(xmlElement); int leafTypeUniqueKey = getUniqueKey(xmlLeafTypeFirstChildElement); EPIC_HACK_mapArrayTypeKeyToLeafTypeKey.put(arrayTypeUniqueKey, leafTypeUniqueKey); } } NamedUserType leafType = (NamedUserType) decode(xmlLeafTypeNode, map); int dimensionCount = Integer.parseInt(xmlDimensionCount.getTextContent()); return UserArrayType.getInstance(leafType, dimensionCount); } private AnonymousUserConstructor decodeAnonymousConstructor( org.w3c.dom.Element xmlElement, java.util.Map<Integer, AbstractDeclaration> map) { org.w3c.dom.Element xmlLeafType = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName( xmlElement, "anonymousType"); org.w3c.dom.Element xmlLeafTypeNode = (org.w3c.dom.Element) xmlLeafType.getChildNodes().item(0); AnonymousUserType anonymousType = (AnonymousUserType) decode(xmlLeafTypeNode, map); return AnonymousUserConstructor.get(anonymousType); } private ClassReflectionProxy decodeDeclaringClass(org.w3c.dom.Element xmlElement) { return decodeType(xmlElement, "declaringClass"); } private ClassReflectionProxy[] decodeParameters(org.w3c.dom.Element xmlElement) { org.w3c.dom.Element xmlParameters = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName( xmlElement, "parameters"); java.util.List<org.w3c.dom.Element> xmlTypes = edu.cmu.cs.dennisc.xml.XMLUtilities.getChildElementsByTagName(xmlParameters, "type"); ClassReflectionProxy[] rv = new ClassReflectionProxy[xmlTypes.size()]; for (int i = 0; i < rv.length; i++) { rv[i] = createClassReflectionProxy(xmlTypes.get(i).getAttribute("name")); } return rv; } private FieldReflectionProxy decodeField(org.w3c.dom.Element xmlParent, String nodeName) { org.w3c.dom.Element xmlField = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName(xmlParent, nodeName); ClassReflectionProxy declaringCls = decodeDeclaringClass(xmlField); String name = xmlField.getAttribute("name"); return new FieldReflectionProxy(declaringCls, name); } private ConstructorReflectionProxy decodeConstructor( org.w3c.dom.Element xmlParent, String nodeName) { org.w3c.dom.Element xmlConstructor = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName(xmlParent, nodeName); ClassReflectionProxy declaringCls = decodeDeclaringClass(xmlConstructor); ClassReflectionProxy[] parameterClses = decodeParameters(xmlConstructor); boolean isVarArgs = Boolean.parseBoolean(xmlConstructor.getAttribute("isVarArgs")); return new ConstructorReflectionProxy(declaringCls, parameterClses, isVarArgs); } private MethodReflectionProxy decodeMethod(org.w3c.dom.Element xmlParent, String nodeName) { org.w3c.dom.Element xmlMethod = edu.cmu.cs.dennisc.xml.XMLUtilities.getSingleChildElementByTagName(xmlParent, nodeName); ClassReflectionProxy declaringCls = decodeDeclaringClass(xmlMethod); String name = xmlMethod.getAttribute("name"); String potentialReplacement = Decoder.intraClassMethodMap.get(declaringCls, name); if (potentialReplacement != null) { name = potentialReplacement; } else { ClassReflectionProxyAndMethodName classReflectionProxyAndMethodName = Decoder.betweenClassesMethodMap.get(declaringCls, name); if (classReflectionProxyAndMethodName != null) { declaringCls = classReflectionProxyAndMethodName.getClassReflectionProxy(); name = classReflectionProxyAndMethodName.getName(); } } // name = filterMethodNameIfNecessary( declaringCls, name ); ClassReflectionProxy[] parameterClses = decodeParameters(xmlMethod); boolean isVarArgs = Boolean.parseBoolean(xmlMethod.getAttribute("isVarArgs")); return new MethodReflectionProxy(declaringCls, name, parameterClses, isVarArgs); } private static int getUniqueKey(org.w3c.dom.Element xmlElement) { return Integer.parseInt(xmlElement.getAttribute(CodecConstants.UNIQUE_KEY_ATTRIBUTE), 16); } public AbstractNode decode( org.w3c.dom.Element xmlElement, java.util.Map<Integer, AbstractDeclaration> map) { AbstractNode rv; if (xmlElement.hasAttribute(CodecConstants.TYPE_ATTRIBUTE)) { String clsName = getClassName(xmlElement); if (clsName.equals(JavaType.class.getName())) { rv = JavaType.getInstance(decodeType(xmlElement, "type")); } else if (clsName.equals(UserArrayType.class.getName())) { rv = decodeUserArrayType(xmlElement, map); } else if (clsName.equals(JavaConstructor.class.getName())) { rv = JavaConstructor.getInstance(decodeConstructor(xmlElement, "constructor")); } else if (clsName.equals(JavaMethod.class.getName())) { MethodReflectionProxy methodReflectionProxy = decodeMethod(xmlElement, "method"); MethodReflectionProxy varArgsReplacement = MethodReflectionProxy.getReplacementIfNecessary(methodReflectionProxy); if (varArgsReplacement != null) { edu.cmu.cs.dennisc.java.util.logging.Logger.errln( "replacing", methodReflectionProxy, "with", varArgsReplacement); methodReflectionProxy = varArgsReplacement; } rv = JavaMethod.getInstance(methodReflectionProxy); } else if (clsName.equals(Getter.class.getName()) || clsName.equals(Setter.class.getName())) { org.w3c.dom.Node xmlFirstChild = xmlElement.getFirstChild(); if (xmlFirstChild instanceof org.w3c.dom.Element) { org.w3c.dom.Element xmlFirstChildElement = (org.w3c.dom.Element) xmlFirstChild; if (xmlFirstChildElement.hasAttribute(CodecConstants.UNIQUE_KEY_ATTRIBUTE)) { int getterOrSetterUniqueKey = getUniqueKey(xmlElement); int fieldUniqueKey = getUniqueKey(xmlFirstChildElement); java.util.Map<Integer, Integer> mapToFieldKey; if (clsName.equals(Getter.class.getName())) { mapToFieldKey = EPIC_HACK_mapGetterKeyToFieldKey; } else { mapToFieldKey = EPIC_HACK_mapSetterKeyToFieldKey; } mapToFieldKey.put(getterOrSetterUniqueKey, fieldUniqueKey); } } org.w3c.dom.NodeList nodeList = xmlElement.getChildNodes(); assert nodeList.getLength() == 1; org.w3c.dom.Element xmlField = (org.w3c.dom.Element) nodeList.item(0); UserField field = (UserField) decode(xmlField, map); if (clsName.equals(Getter.class.getName())) { rv = field.getGetter(); } else { rv = field.getSetter(); } } else if (clsName.equals(SetterParameter.class.getName())) { org.w3c.dom.NodeList nodeList = xmlElement.getChildNodes(); assert nodeList.getLength() == 1; org.w3c.dom.Element xmlSetter = (org.w3c.dom.Element) nodeList.item(0); Setter setter = (Setter) decode(xmlSetter, map); rv = setter.getRequiredParameters().get(0); } else if (clsName.equals(JavaField.class.getName())) { rv = JavaField.getInstance(decodeField(xmlElement, "field")); } else if (clsName.equals(AnonymousUserConstructor.class.getName())) { rv = decodeAnonymousConstructor(xmlElement, map); } else if (clsName.equals(JavaConstructorParameter.class.getName())) { org.w3c.dom.NodeList nodeList = xmlElement.getChildNodes(); assert nodeList.getLength() == 2; org.w3c.dom.Element xmlConstructor = (org.w3c.dom.Element) nodeList.item(0); JavaConstructor constructorDeclaredInJava = (JavaConstructor) decodeValue(xmlConstructor, map); org.w3c.dom.Element xmlIndex = (org.w3c.dom.Element) nodeList.item(1); int index = Integer.parseInt(xmlIndex.getTextContent()); final int REQUIRED_N = constructorDeclaredInJava.getRequiredParameters().size(); if (index < REQUIRED_N) { rv = constructorDeclaredInJava.getRequiredParameters().get(index); } else { if (index == REQUIRED_N) { rv = constructorDeclaredInJava.getVariableLengthParameter(); if (rv != null) { // pass; } else { rv = constructorDeclaredInJava.getKeyedParameter(); } } else { rv = null; } } } else if (clsName.equals(JavaMethodParameter.class.getName())) { org.w3c.dom.NodeList nodeList = xmlElement.getChildNodes(); assert nodeList.getLength() == 2; org.w3c.dom.Element xmlMethod = (org.w3c.dom.Element) nodeList.item(0); JavaMethod methodDeclaredInJava = (JavaMethod) decodeValue(xmlMethod, map); org.w3c.dom.Element xmlIndex = (org.w3c.dom.Element) nodeList.item(1); int index = Integer.parseInt(xmlIndex.getTextContent()); final int REQUIRED_N = methodDeclaredInJava.getRequiredParameters().size(); if (index < REQUIRED_N) { rv = methodDeclaredInJava.getRequiredParameters().get(index); } else { if (index == REQUIRED_N) { rv = methodDeclaredInJava.getVariableLengthParameter(); if (rv != null) { // pass; } else { rv = methodDeclaredInJava.getKeyedParameter(); } } else { rv = null; } } } else { rv = (AbstractNode) newInstance(xmlElement); assert rv != null; } if (rv instanceof AbstractDeclaration) { map.put(getUniqueKey(xmlElement), (AbstractDeclaration) rv); } rv.decodeNode(this, xmlElement, map); if (xmlElement.hasAttribute(CodecConstants.ID_ATTRIBUTE)) { if (this.policy.isIdPreserved()) { rv.setId(java.util.UUID.fromString(xmlElement.getAttribute(CodecConstants.ID_ATTRIBUTE))); } } } else { int key = getUniqueKey(xmlElement); rv = map.get(key); if (rv != null) { // pass } else { if (EPIC_HACK_mapArrayTypeKeyToLeafTypeKey.containsKey(key)) { int leafTypeKey = EPIC_HACK_mapArrayTypeKeyToLeafTypeKey.get(key); AbstractDeclaration leafDeclaration = map.get(leafTypeKey); if (leafDeclaration instanceof UserType<?>) { UserType<?> leafType = (UserType<?>) leafDeclaration; edu.cmu.cs.dennisc.java.util.logging.Logger.outln(leafTypeKey, leafType); rv = leafType.getArrayType(); } else { assert false : leafDeclaration; } } else if (EPIC_HACK_mapGetterKeyToFieldKey.containsKey(key)) { int fieldKey = EPIC_HACK_mapGetterKeyToFieldKey.get(key); AbstractDeclaration fieldDeclaration = map.get(fieldKey); if (fieldDeclaration instanceof UserField) { UserField userField = (UserField) fieldDeclaration; rv = userField.getGetter(); } } else if (EPIC_HACK_mapSetterKeyToFieldKey.containsKey(key)) { int fieldKey = EPIC_HACK_mapSetterKeyToFieldKey.get(key); AbstractDeclaration fieldDeclaration = map.get(fieldKey); if (fieldDeclaration instanceof UserField) { UserField userField = (UserField) fieldDeclaration; rv = userField.getSetter(); } } else { assert false : Integer.toHexString(key) + " " + map; } } } return rv; } private final java.util.Map<Integer, Integer> EPIC_HACK_mapArrayTypeKeyToLeafTypeKey = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); private final java.util.Map<Integer, Integer> EPIC_HACK_mapGetterKeyToFieldKey = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); private final java.util.Map<Integer, Integer> EPIC_HACK_mapSetterKeyToFieldKey = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); private final org.lgna.project.Version srcVersion; private final org.lgna.project.Version dstVersion; private final DecodeIdPolicy policy; }