##### Coverage Report - com.ctrip.apollo.portal.service.ConfigService

Classes in this File | Line Coverage | Branch Coverage | Complexity
ConfigService |
72% | 62/86
83% | 15/18
| 3.0;3

1 |  |
     package com.ctrip.apollo.portal.service;
2 |  |
3 |  |
     import com.google.gson.Gson;
4 |  |
5 |  |
     import org.slf4j.Logger;
6 |  |
     import org.slf4j.LoggerFactory;
7 |  |
     import org.springframework.beans.factory.annotation.Autowired;
8 |  |
     import org.springframework.http.HttpStatus;
9 |  |
     import org.springframework.stereotype.Service;
10 |  |
     import org.springframework.util.CollectionUtils;
11 |  |
     import org.springframework.web.client.HttpClientErrorException;
12 |  |
13 |  |
     import com.ctrip.apollo.common.utils.BeanUtils;
14 |  |
     import com.ctrip.apollo.common.utils.ExceptionUtils;
15 |  |
     import com.ctrip.apollo.core.enums.Env;
16 |  |
     import com.ctrip.apollo.core.dto.ItemChangeSets;
17 |  |
     import com.ctrip.apollo.core.dto.ItemDTO;
18 |  |
     import com.ctrip.apollo.core.dto.NamespaceDTO;
19 |  |
     import com.ctrip.apollo.core.dto.ReleaseDTO;
20 |  |
     import com.ctrip.apollo.core.exception.BadRequestException;
21 |  |
     import com.ctrip.apollo.core.exception.NotFoundException;
22 |  |
     import com.ctrip.apollo.core.exception.ServiceException;
23 |  |
     import com.ctrip.apollo.core.utils.StringUtils;
24 |  |
     import com.ctrip.apollo.portal.api.AdminServiceAPI;
25 |  |
     import com.ctrip.apollo.portal.entity.ItemDiffs;
26 |  |
     import com.ctrip.apollo.portal.entity.NamespaceIdentifer;
27 |  |
     import com.ctrip.apollo.portal.entity.form.NamespaceTextModel;
28 |  |
     import com.ctrip.apollo.portal.entity.NamespaceVO;
29 |  |
     import com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel;
30 |  |
     import com.ctrip.apollo.portal.service.txtresolver.ConfigTextResolver;
31 |  |
32 |  |
     import java.util.Collections;
33 |  |
     import java.util.HashMap;
34 |  |
     import java.util.LinkedList;
35 |  |
     import java.util.List;
36 |  |
     import java.util.Map;
37 |  |
38 |  |
     @Service
39 | 4 |
     public class ConfigService {
40 |  |
41 | 4 |
       private Logger logger = LoggerFactory.getLogger(ConfigService.class);
42 |  |
43 |  |
       @Autowired
44 |  |
       private AdminServiceAPI.NamespaceAPI namespaceAPI;
45 |  |
       @Autowired
46 |  |
       private AdminServiceAPI.ItemAPI itemAPI;
47 |  |
       @Autowired
48 |  |
       private AdminServiceAPI.ReleaseAPI releaseAPI;
49 |  |
50 |  |
       @Autowired
51 |  |
       private ConfigTextResolver resolver;
52 |  |
53 |  |
54 |  |
       /**
55 |  |
        * parse config text and update config items
56 |  |
        *
57 |  |
        * @return parse result
58 |  |
        */
59 |  |
       public void updateConfigItemByText(NamespaceTextModel model) {
60 | 1 |
         String appId = model.getAppId();
61 | 1 |
         Env env = model.getEnv();
62 | 1 |
         String clusterName = model.getClusterName();
63 | 1 |
         String namespaceName = model.getNamespaceName();
64 | 1 |
         long namespaceId = model.getNamespaceId();
65 | 1 |
         String configText = model.getConfigText();
66 |  |
67 | 2 |
         ItemChangeSets changeSets = resolver.resolve(namespaceId, configText,
68 | 1 |
                                                      itemAPI.findItems(appId, env, clusterName, namespaceName));
69 | 1 |
         if (changeSets.isEmpty()) {
70 | 0 |
           return;
71 |  |
         }
72 |  |
         try {
73 | 1 |
           itemAPI.updateItems(appId, env, clusterName, namespaceName, changeSets);
74 | 0 |
         } catch (Exception e) {
75 | 0 |
           logger.error("itemAPI.updateItems error. appId{},env:{},clusterName:{},namespaceName:{}", appId, env, clusterName,
76 |  |
                        namespaceName);
77 | 0 |
           throw new ServiceException(e.getMessage());
78 | 1 |
         }
79 | 1 |
       }
80 |  |
81 |  |
       /**
82 |  |
        * createRelease config items
83 |  |
        */
84 |  |
       public ReleaseDTO createRelease(NamespaceReleaseModel model) {
85 | 0 |
         return releaseAPI.release(model.getAppId(), model.getEnv(), model.getClusterName(),
86 | 0 |
                                   model.getNamespaceName(), model.getReleaseBy(), model.getReleaseComment());
87 |  |
       }
88 |  |
89 |  |
       public List<ItemDTO> findItems(String appId, Env env, String clusterName, String namespaceName) {
90 | 0 |
         return itemAPI.findItems(appId, env, clusterName, namespaceName);
91 |  |
       }
92 |  |
93 |  |
       public void syncItems(List<NamespaceIdentifer> comparedNamespaces, List<ItemDTO> sourceItems){
94 | 0 |
         List<ItemDiffs> itemDiffs = compare(comparedNamespaces, sourceItems);
95 | 0 |
         for (ItemDiffs itemDiff: itemDiffs){
96 | 0 |
           NamespaceIdentifer namespaceIdentifer = itemDiff.getNamespace();
97 |  |
           try {
98 | 0 |
             itemAPI
99 | 0 |
                 .updateItems(namespaceIdentifer.getAppId(), namespaceIdentifer.getEnv(),
100 | 0 |
                              namespaceIdentifer.getClusterName(),
101 | 0 |
                              namespaceIdentifer.getNamespaceName(), itemDiff.getDiffs());
102 | 0 |
           } catch (HttpClientErrorException e) {
103 | 0 |
             logger.error("sync items error. namespace:{}", namespaceIdentifer);
104 | 0 |
             throw new ServiceException(String.format("sync item error. env:%s, clusterName:%s", namespaceIdentifer.getEnv(),
105 | 0 |
                                                      namespaceIdentifer.getClusterName()), e);
106 | 0 |
           }
107 | 0 |
         }
108 | 0 |
       }
109 |  |
110 |  |
       public List<ItemDiffs> compare(List<NamespaceIdentifer> comparedNamespaces, List<ItemDTO> sourceItems) {
111 |  |
112 | 2 |
         List<ItemDiffs> result = new LinkedList<>();
113 |  |
114 | 2 |
         for (NamespaceIdentifer namespace : comparedNamespaces) {
115 |  |
116 | 2 |
           ItemDiffs itemDiffs = new ItemDiffs(namespace);
117 | 2 |
           itemDiffs.setDiffs(parseChangeSets(namespace, sourceItems));
118 | 2 |
           result.add(itemDiffs);
119 | 2 |
         }
120 |  |
121 | 2 |
         return result;
122 |  |
       }
123 |  |
124 |  |
       private long getNamespaceId(NamespaceIdentifer namespaceIdentifer) {
125 | 2 |
         String appId = namespaceIdentifer.getAppId();
126 | 2 |
         String clusterName = namespaceIdentifer.getClusterName();
127 | 2 |
         String namespaceName = namespaceIdentifer.getNamespaceName();
128 | 2 |
         Env env = namespaceIdentifer.getEnv();
129 | 2 |
         NamespaceDTO namespaceDTO = null;
130 |  |
         try {
131 | 2 |
           namespaceDTO = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);
132 | 0 |
         } catch (NotFoundException e) {
133 | 0 |
           logger.warn("namespace not exist. appId:{}, env:{}, clusterName:{}, namespaceName:{}", appId, env, clusterName,
134 |  |
                       namespaceName);
135 | 0 |
           throw new BadRequestException(String.format(
136 |  |
               "namespace not exist. appId:%s, env:%s, clusterName:%s, namespaceName:%s", appId, env, clusterName,
137 |  |
               namespaceName));
138 | 2 |
         }
139 | 2 |
         return namespaceDTO.getId();
140 |  |
       }
141 |  |
142 |  |
       private ItemChangeSets parseChangeSets(NamespaceIdentifer namespace, List<ItemDTO> sourceItems){
143 | 2 |
         ItemChangeSets changeSets = new ItemChangeSets();
144 |  |
         List<ItemDTO>
145 | 2 |
             targetItems =
146 | 4 |
             itemAPI.findItems(namespace.getAppId(), namespace.getEnv(),
147 | 2 |
                               namespace.getClusterName(), namespace.getNamespaceName());
148 |  |
149 | 2 |
         long namespaceId = getNamespaceId(namespace);
150 | 2 |
         if (CollectionUtils.isEmpty(targetItems)) {//all source items is added
151 | 1 |
           int lineNum = 1;
152 | 1 |
           for (ItemDTO sourceItem : sourceItems) {
153 | 1 |
             changeSets.addCreateItem(buildItem(namespaceId, lineNum++, sourceItem));
154 | 1 |
           }
155 | 1 |
         } else {
156 | 1 |
           Map<String, ItemDTO> keyMapItem = BeanUtils.mapByKey("key", targetItems);
157 |  |
           String key, sourceValue, sourceComment;
158 | 1 |
           ItemDTO targetItem = null;
159 | 1 |
           int maxLineNum = targetItems.size();//append to last
160 | 1 |
           for (ItemDTO sourceItem : sourceItems) {
161 | 4 |
             key = sourceItem.getKey();
162 | 4 |
             sourceValue = sourceItem.getValue();
163 | 4 |
             sourceComment = sourceItem.getComment();
164 | 4 |
             targetItem = keyMapItem.get(key);
165 |  |
166 | 4 |
             if (targetItem == null) {//added items
167 |  |
168 | 1 |
               changeSets.addCreateItem(buildItem(namespaceId, ++maxLineNum, sourceItem));
169 |  |
170 | 3 |
             } else if (!sourceValue.equals(targetItem.getValue()) || !sourceComment
171 | 2 |
                 .equals(targetItem.getComment())) {//modified items
172 | 2 |
               targetItem.setValue(sourceValue);
173 | 2 |
               targetItem.setComment(sourceComment);
174 | 2 |
               changeSets.addUpdateItem(targetItem);
175 |  |
             }
176 | 4 |
           }
177 |  |
         }
178 |  |
179 | 2 |
         return changeSets;
180 |  |
       }
181 |  |
182 |  |
       private ItemDTO buildItem(long namespaceId, int lineNum, ItemDTO sourceItem) {
183 | 2 |
         ItemDTO createdItem = new ItemDTO();
184 | 2 |
         BeanUtils.copyEntityProperties(sourceItem, createdItem);
185 | 2 |
         createdItem.setLineNum(lineNum++);
186 | 2 |
         createdItem.setNamespaceId(namespaceId);
187 | 2 |
         return createdItem;
188 |  |
       }
189 |  |
     }