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

Classes in this File | Line Coverage | Branch Coverage | Complexity
ConfigService |
64% | 74/115
64% | 22/34
| 3.3636363636363638;3.364

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