/**
* 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.isis.core.runtime.services.command;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.PostConstruct;
import com.google.common.collect.Lists;
import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.services.background.ActionInvocationMemento;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.bookmark.BookmarkService;
import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.command.CommandContext;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.adapter.oid.RootOid;
import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
import org.apache.isis.core.metamodel.services.command.CommandDtoServiceInternal;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
import org.apache.isis.schema.cmd.v1.ActionDto;
import org.apache.isis.schema.cmd.v1.CommandDto;
import org.apache.isis.schema.cmd.v1.ParamDto;
import org.apache.isis.schema.cmd.v1.ParamsDto;
import org.apache.isis.schema.cmd.v1.PropertyDto;
import org.apache.isis.schema.common.v1.InteractionType;
import org.apache.isis.schema.common.v1.OidsDto;
import org.apache.isis.schema.common.v1.ValueWithTypeDto;
import org.apache.isis.schema.utils.CommandDtoUtils;
import org.apache.isis.schema.utils.CommonDtoUtils;
@DomainService(
nature = NatureOfService.DOMAIN,
menuOrder = "" + Integer.MAX_VALUE
)
public class CommandDtoServiceInternalDefault implements CommandDtoServiceInternal {
private final MementoServiceDefault mementoService;
public CommandDtoServiceInternalDefault() {
this(new MementoServiceDefault());
}
CommandDtoServiceInternalDefault(MementoServiceDefault mementoService) {
this.mementoService = mementoService.withNoEncoding();
}
// //////////////////////////////////////
@Programmatic
@PostConstruct
public void init(Map<String,String> props) {
}
// //////////////////////////////////////
private ObjectSpecificationDefault getJavaSpecificationOfOwningClass(final Method method) {
return getJavaSpecification(method.getDeclaringClass());
}
private ObjectSpecificationDefault getJavaSpecification(final Class<?> cls) {
final ObjectSpecification objectSpec = getSpecification(cls);
if (!(objectSpec instanceof ObjectSpecificationDefault)) {
throw new UnsupportedOperationException(
"Only Java is supported "
+ "(specification is '" + objectSpec.getClass().getCanonicalName() + "')");
}
return (ObjectSpecificationDefault) objectSpec;
}
private ObjectSpecification getSpecification(final Class<?> type) {
return specificationLoader.loadSpecification(type);
}
// //////////////////////////////////////
@Deprecated
@Programmatic
@Override
public ActionInvocationMemento asActionInvocationMemento(
final Method method,
final Object domainObject,
final Object[] args) {
final ObjectSpecificationDefault targetObjSpec = getJavaSpecificationOfOwningClass(method);
final ObjectMember member = targetObjSpec.getMember(method);
if(member == null) {
return null;
}
if(!(member instanceof ObjectAction)) {
throw new UnsupportedOperationException(String.format(
"Method %s does not correspond to an action.", method.getName()));
}
final ObjectAction action = (ObjectAction) member;
final String actionIdentifier = CommandUtil.memberIdentifierFor(action);
final Bookmark domainObjectBookmark = bookmarkService.bookmarkFor(domainObject);
final List<Class<?>> argTypes = Lists.newArrayList();
final List<Object> argObjs = Lists.newArrayList();
CommandUtil.buildMementoArgLists(mementoService, bookmarkService, method, args, argTypes, argObjs);
final ActionInvocationMemento aim =
new ActionInvocationMemento(mementoService,
actionIdentifier,
domainObjectBookmark,
argTypes,
argObjs);
return aim;
}
@Override
public CommandDto asCommandDto(
final List<ObjectAdapter> targetAdapters,
final ObjectAction objectAction,
final ObjectAdapter[] argAdapters) {
final CommandDto dto = asCommandDto(targetAdapters);
final ActionDto actionDto = new ActionDto();
actionDto.setInteractionType(InteractionType.ACTION_INVOCATION);
dto.setMember(actionDto);
addActionArgs(objectAction, actionDto, argAdapters);
return dto;
}
@Override
public CommandDto asCommandDto(
final List<ObjectAdapter> targetAdapters,
final OneToOneAssociation property,
final ObjectAdapter valueAdapterOrNull) {
final CommandDto dto = asCommandDto(targetAdapters);
final PropertyDto propertyDto = new PropertyDto();
propertyDto.setInteractionType(InteractionType.PROPERTY_EDIT);
dto.setMember(propertyDto);
addPropertyValue(property, propertyDto, valueAdapterOrNull);
return dto;
}
private CommandDto asCommandDto(final List<ObjectAdapter> targetAdapters) {
final CommandDto dto = new CommandDto();
dto.setMajorVersion("1");
dto.setMinorVersion("0");
String transactionId = determineTransactionId().toString();
dto.setTransactionId(transactionId);
for (ObjectAdapter targetAdapter : targetAdapters) {
final RootOid rootOid = (RootOid) targetAdapter.getOid();
final Bookmark bookmark = rootOid.asBookmark();
final OidsDto targets = CommandDtoUtils.targetsFor(dto);
targets.getOid().add(bookmark.toOidDto());
}
return dto;
}
protected UUID determineTransactionId() {
Command command = commandContext.getCommand();
if (command != null && command.getTransactionId() != null) {
return command.getTransactionId();
} else {
return UUID.randomUUID();
}
}
@Override
public void addActionArgs(
final ObjectAction objectAction,
final ActionDto actionDto,
final ObjectAdapter[] argAdapters) {
final String actionId = CommandUtil.memberIdentifierFor(objectAction);
actionDto.setMemberIdentifier(actionId);
List<ObjectActionParameter> actionParameters = objectAction.getParameters();
for (int paramNum = 0; paramNum < actionParameters.size(); paramNum++) {
final ObjectActionParameter actionParameter = actionParameters.get(paramNum);
final String parameterName = actionParameter.getName();
final Class<?> paramType = actionParameter.getSpecification().getCorrespondingClass();
final ObjectAdapter argAdapter = argAdapters[paramNum];
final Object arg = argAdapter != null? argAdapter.getObject(): null;
final ParamsDto parameters = CommandDtoUtils.parametersFor(actionDto);
final List<ParamDto> parameterList = parameters.getParameter();
ParamDto paramDto = CommonDtoUtils.newParamDto(
parameterName, paramType, arg, bookmarkService);
parameterList.add(paramDto);
}
}
@Override
public void addPropertyValue(
final OneToOneAssociation property,
final PropertyDto propertyDto,
final ObjectAdapter valueAdapter) {
final String actionIdentifier = CommandUtil.memberIdentifierFor(property);
propertyDto.setMemberIdentifier(actionIdentifier);
final ObjectSpecification valueSpec = property.getSpecification();
final Class<?> valueType = valueSpec.getCorrespondingClass();
final ValueWithTypeDto newValue = CommonDtoUtils.newValueWithTypeDto(
valueType, ObjectAdapter.Util.unwrap(valueAdapter), bookmarkService);
propertyDto.setNewValue(newValue);
}
// //////////////////////////////////////
//region > injected services
@javax.inject.Inject
CommandContext commandContext;
@javax.inject.Inject
private BookmarkService bookmarkService;
@javax.inject.Inject
SpecificationLoader specificationLoader;
@javax.inject.Inject
IsisSessionFactory isisSessionFactory;
protected AdapterManager getAdapterManager() {
return isisSessionFactory.getCurrentSession().getPersistenceSession();
}
//endregion
}