blob: 3d3e70a7a39ea510f23aee7a3297a83bd40ad661 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.causeway.core.runtimeservices.executor;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
import org.apache.causeway.applib.services.iactnlayer.InteractionLayerTracker;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.internal.debug.xray.XrayUi;
import org.apache.causeway.core.metamodel.execution.InteractionInternal;
import org.apache.causeway.core.metamodel.interactions.InteractionHead;
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.object.MmUnwrapUtils;
import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.causeway.core.security.util.XrayUtil;
import org.apache.causeway.core.security.util.XrayUtil.SequenceHandle;
import lombok.NonNull;
import lombok.val;
final class _Xray {
static SequenceHandle enterActionInvocation(
final @NonNull InteractionLayerTracker iaTracker,
final @NonNull InteractionInternal interaction,
final @NonNull ObjectAction owningAction,
final @NonNull InteractionHead head,
final @NonNull Can<ManagedObject> argumentAdapters) {
if(!XrayUi.isXrayEnabled()) {
return null;
}
val participantLabel = owningAction.getFeatureIdentifier().getLogicalIdentityString("\n#");
val enteringLabel = argumentAdapters.isEmpty()
? "action invocation (no args)"
: String.format("action invocation w/ %d args:\n %s",
argumentAdapters.size(),
argumentAdapters.stream()
.map(MmUnwrapUtils::single)
.map(obj->"" + obj)
.collect(Collectors.joining(",\n ")));
return enterInvocation(iaTracker, interaction, participantLabel, enteringLabel);
}
public static SequenceHandle enterPropertyEdit(
final @NonNull InteractionLayerTracker iaTracker,
final @NonNull InteractionInternal interaction,
final @NonNull OneToOneAssociation owningProperty,
final @NonNull InteractionHead head,
final @NonNull ManagedObject newValueAdapter) {
if(!XrayUi.isXrayEnabled()) {
return null;
}
val participantLabel = owningProperty.getFeatureIdentifier().getLogicalIdentityString("\n#");
val enteringLabel = String.format("property edit -> '%s'",
MmUnwrapUtils.single(newValueAdapter));
return enterInvocation(iaTracker, interaction, participantLabel, enteringLabel);
}
private static SequenceHandle enterInvocation(
final @NonNull InteractionLayerTracker iaTracker,
final InteractionInternal interaction,
final String participantLabel,
final String enteringLabel) {
// val execution = interaction.getCurrentExecution(); // XXX why not populated?
val handleIfAny = XrayUtil.createSequenceHandle(iaTracker, "executor", participantLabel);
handleIfAny.ifPresent(handle->{
handle.submit(sequenceData->{
sequenceData.alias("executor", "Member-\nExecutorService-\n(Default)");
val callee1 = handle.getCallees().getFirstElseFail();
val callee2 = handle.getCallees().getLastElseFail();
sequenceData.enter(handle.getCaller(), callee1);
sequenceData.activate(callee1);
sequenceData.enter(callee1, callee2, enteringLabel);
sequenceData.activate(callee2);
});
});
return handleIfAny.orElse(null);
}
static void exitInvocation(final @Nullable SequenceHandle handle) {
if(handle==null) {
return; // x-ray is not enabled
}
handle.submit(sequenceData->{
val callee1 = handle.getCallees().getFirstElseFail();
val callee2 = handle.getCallees().getLastElseFail();
sequenceData.exit(callee2, callee1);
sequenceData.deactivate(callee2);
sequenceData.exit(callee1, handle.getCaller());
sequenceData.deactivate(callee1);
});
}
}