content: package com.ctrip.framework.apollo.adminservice.controller;
  
  import com.ctrip.framework.apollo.adminservice.aop.PreAcquireNamespaceLock;
  import com.ctrip.framework.apollo.biz.entity.Commit;
  import com.ctrip.framework.apollo.biz.entity.Item;
  import com.ctrip.framework.apollo.biz.entity.Namespace;
  import com.ctrip.framework.apollo.biz.service.CommitService;
  import com.ctrip.framework.apollo.biz.service.ItemService;
  import com.ctrip.framework.apollo.biz.service.NamespaceService;
  import com.ctrip.framework.apollo.biz.utils.ConfigChangeContentBuilder;
  import com.ctrip.framework.apollo.common.dto.ItemDTO;
  import com.ctrip.framework.apollo.common.exception.BadRequestException;
  import com.ctrip.framework.apollo.common.exception.NotFoundException;
  import com.ctrip.framework.apollo.common.utils.BeanUtils;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.web.bind.annotation.PathVariable;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RequestMethod;
  import org.springframework.web.bind.annotation.RequestParam;
  import org.springframework.web.bind.annotation.RestController;
  
  import java.util.List;
  
  @RestController
  public class ItemController {
  
    @Autowired
    private ItemService itemService;
    @Autowired
    private NamespaceService namespaceService;
    @Autowired
    private CommitService commitService;
  
    @PreAcquireNamespaceLock
    @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST)
    public ItemDTO create(@PathVariable("appId") String appId,
                          @PathVariable("clusterName") String clusterName,
                          @PathVariable("namespaceName") String namespaceName, @RequestBody ItemDTO dto) {
      Item entity = BeanUtils.transfrom(Item.class, dto);
  
      ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder();
      Item managedEntity = itemService.findOne(appId, clusterName, namespaceName, entity.getKey());
      if (managedEntity != null) {
        throw new BadRequestException("item already exist");
      } else {
        entity = itemService.save(entity);
        builder.createItem(entity);
      }
      dto = BeanUtils.transfrom(ItemDTO.class, entity);
  
      Commit commit = new Commit();
      commit.setAppId(appId);
      commit.setClusterName(clusterName);
      commit.setNamespaceName(namespaceName);
      commit.setChangeSets(builder.build());
      commit.setDataChangeCreatedBy(dto.getDataChangeLastModifiedBy());
      commit.setDataChangeLastModifiedBy(dto.getDataChangeLastModifiedBy());
      commitService.save(commit);
  
      return dto;
    }
  
    @PreAcquireNamespaceLock
    @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", method = RequestMethod.PUT)
    public ItemDTO update(@PathVariable("appId") String appId,
                          @PathVariable("clusterName") String clusterName,
                          @PathVariable("namespaceName") String namespaceName,
                          @PathVariable("itemId") long itemId,
                          @RequestBody ItemDTO itemDTO) {
  
      Item entity = BeanUtils.transfrom(Item.class, itemDTO);
  
      ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder();
  
      Item managedEntity = itemService.findOne(itemId);
      if (managedEntity == null) {
        throw new BadRequestException("item not exist");
      }
  
      Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedEntity);
  
      //protect. only value,comment,lastModifiedBy can be modified
      managedEntity.setValue(entity.getValue());
      managedEntity.setComment(entity.getComment());
      managedEntity.setDataChangeLastModifiedBy(entity.getDataChangeLastModifiedBy());
  
      entity = itemService.update(managedEntity);
      builder.updateItem(beforeUpdateItem, entity);
      itemDTO = BeanUtils.transfrom(ItemDTO.class, entity);
  
      if (builder.hasContent()) {
        Commit commit = new Commit();
        commit.setAppId(appId);
        commit.setClusterName(clusterName);
        commit.setNamespaceName(namespaceName);
        commit.setChangeSets(builder.build());
        commit.setDataChangeCreatedBy(itemDTO.getDataChangeLastModifiedBy());
        commit.setDataChangeLastModifiedBy(itemDTO.getDataChangeLastModifiedBy());
        commitService.save(commit);
      }
  
      return itemDTO;
    }
  
    @PreAcquireNamespaceLock
    @RequestMapping(path = "/items/{itemId}", method = RequestMethod.DELETE)
    public void delete(@PathVariable("itemId") long itemId, @RequestParam String operator) {
      Item entity = itemService.findOne(itemId);
      if (entity == null) {
        throw new NotFoundException("item not found for itemId " + itemId);
      }
      itemService.delete(entity.getId(), operator);
  
      Namespace namespace = namespaceService.findOne(entity.getNamespaceId());
  
      Commit commit = new Commit();
      commit.setAppId(namespace.getAppId());
      commit.setClusterName(namespace.getClusterName());
      commit.setNamespaceName(namespace.getNamespaceName());
      commit.setChangeSets(new ConfigChangeContentBuilder().deleteItem(entity).build());
      commit.setDataChangeCreatedBy(operator);
      commit.setDataChangeLastModifiedBy(operator);
      commitService.save(commit);
    }
  
    @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.GET)
    public List<ItemDTO> findItems(@PathVariable("appId") String appId,
                                   @PathVariable("clusterName") String clusterName,
                                   @PathVariable("namespaceName") String namespaceName) {
      return BeanUtils.batchTransform(ItemDTO.class, itemService.findItemsWithOrdered(appId, clusterName, namespaceName));
    }
  
    @RequestMapping(value = "/items/{itemId}", method = RequestMethod.GET)
    public ItemDTO get(@PathVariable("itemId") long itemId) {
      Item item = itemService.findOne(itemId);
      if (item == null) {
        throw new NotFoundException("item not found for itemId " + itemId);
      }
      return BeanUtils.transfrom(ItemDTO.class, item);
    }
  
    @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}", method = RequestMethod.GET)
    public ItemDTO get(@PathVariable("appId") String appId,
                       @PathVariable("clusterName") String clusterName,
                       @PathVariable("namespaceName") String namespaceName, @PathVariable("key") String key) {
      Item item = itemService.findOne(appId, clusterName, namespaceName, key);
      if (item == null) {
        throw new NotFoundException(
            String.format("item not found for %s %s %s %s", appId, clusterName, namespaceName, key));
      }
      return BeanUtils.transfrom(ItemDTO.class, item);
    }
  
  
  }
  