Project

General

Profile

Download (14.7 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2009 EDIT European Distributed Institute of Taxonomy
3
 * http://www.e-taxonomy.eu
4
 *
5
 * The contents of this file are subject to the Mozilla Public License Version
6
 * 1.1 See LICENSE.TXT at the top of this package for the full license terms.
7
 */
8

    
9
package eu.etaxonomy.cdm.remote.controller;
10

    
11
import java.awt.Color;
12
import java.io.IOException;
13
import java.util.ArrayList;
14
import java.util.Arrays;
15
import java.util.EnumSet;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20
import java.util.stream.Collectors;
21

    
22
import javax.servlet.http.HttpServletRequest;
23
import javax.servlet.http.HttpServletResponse;
24

    
25
import org.springframework.beans.factory.annotation.Autowired;
26
import org.springframework.beans.factory.annotation.Qualifier;
27
import org.springframework.stereotype.Controller;
28
import org.springframework.web.bind.WebDataBinder;
29
import org.springframework.web.bind.annotation.InitBinder;
30
import org.springframework.web.bind.annotation.PathVariable;
31
import org.springframework.web.bind.annotation.RequestMapping;
32
import org.springframework.web.bind.annotation.RequestMethod;
33
import org.springframework.web.bind.annotation.RequestParam;
34
import org.springframework.web.servlet.ModelAndView;
35

    
36
import com.fasterxml.jackson.core.JsonParseException;
37
import com.fasterxml.jackson.databind.JsonMappingException;
38

    
39
import eu.etaxonomy.cdm.api.application.ICdmRepository;
40
import eu.etaxonomy.cdm.api.service.IDescriptionService;
41
import eu.etaxonomy.cdm.api.service.ITermService;
42
import eu.etaxonomy.cdm.api.service.IVocabularyService;
43
import eu.etaxonomy.cdm.api.service.description.AggregationMode;
44
import eu.etaxonomy.cdm.api.service.description.DistributionAggregation;
45
import eu.etaxonomy.cdm.api.service.description.DistributionAggregationConfiguration;
46
import eu.etaxonomy.cdm.api.service.dto.DistributionInfoDTO;
47
import eu.etaxonomy.cdm.api.service.dto.DistributionInfoDTO.InfoPart;
48
import eu.etaxonomy.cdm.api.service.l10n.LocaleContext;
49
import eu.etaxonomy.cdm.api.service.pager.Pager;
50
import eu.etaxonomy.cdm.api.util.DistributionOrder;
51
import eu.etaxonomy.cdm.common.monitor.IRestServiceProgressMonitor;
52
import eu.etaxonomy.cdm.ext.geo.CondensedDistributionConfiguration;
53
import eu.etaxonomy.cdm.ext.geo.CondensedDistributionRecipe;
54
import eu.etaxonomy.cdm.ext.geo.EditGeoServiceUtilities;
55
import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
56
import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
57
import eu.etaxonomy.cdm.model.common.MarkerType;
58
import eu.etaxonomy.cdm.model.description.DescriptionBase;
59
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
60
import eu.etaxonomy.cdm.model.location.NamedArea;
61
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
62
import eu.etaxonomy.cdm.model.location.NamedAreaType;
63
import eu.etaxonomy.cdm.model.name.Rank;
64
import eu.etaxonomy.cdm.persistence.dto.TermDto;
65
import eu.etaxonomy.cdm.persistence.query.OrderHint;
66
import eu.etaxonomy.cdm.remote.controller.util.PagerParameters;
67
import eu.etaxonomy.cdm.remote.controller.util.ProgressMonitorUtil;
68
import eu.etaxonomy.cdm.remote.editor.DefinedTermBaseList;
69
import eu.etaxonomy.cdm.remote.editor.TermBaseListPropertyEditor;
70
import eu.etaxonomy.cdm.remote.editor.TermBasePropertyEditor;
71
import eu.etaxonomy.cdm.remote.editor.UUIDListPropertyEditor;
72
import eu.etaxonomy.cdm.remote.editor.UuidList;
73
import io.swagger.annotations.Api;
74

    
75
/**
76
 * TODO write controller documentation
77
 *
78
 * @author a.kohlbecker
79
 * @since 24.03.2009
80
 */
81
@Controller
82
@Api("description")
83
@RequestMapping(value = {"/description"})
84
public class DescriptionListController
85
        extends AbstractIdentifiableListController<DescriptionBase, IDescriptionService> {
86

    
87
    @Autowired
88
    private ITermService termService;
89

    
90
    @Autowired
91
    private IVocabularyService vocabularyService ;
92

    
93
    @Autowired
94
    private IEditGeoService geoService;
95

    
96
    @Autowired
97
    @Qualifier("cdmRepository")
98
    private ICdmRepository repository;
99

    
100
    @Autowired
101
    public ProgressMonitorController progressMonitorController;
102

    
103
    protected static final List<String> DESCRIPTION_ELEMENT_INIT_STRATEGY = Arrays.asList(new String []{
104
            "$",
105
            "multilanguageText",
106
    });
107

    
108
    /**
109
     * There should only be one longtime processes
110
     * therefore the according progress monitor uuid is stored in
111
     * this static field.
112
     */
113
    private static UUID transmissionEngineMonitorUuid = null;
114

    
115

    
116
    @Override
117
    @Autowired
118
    public void setService(IDescriptionService service) {
119
        this.service = service;
120
    }
121

    
122
    @InitBinder
123
    @Override
124
    public void initBinder(WebDataBinder binder) {
125
        super.initBinder(binder);
126
        binder.registerCustomEditor(DefinedTermBaseList.class, new TermBaseListPropertyEditor<>(termService));
127
        binder.registerCustomEditor(NamedAreaLevel.class, new TermBasePropertyEditor<>(termService));
128
        binder.registerCustomEditor(Rank.class, new TermBasePropertyEditor<>(termService));
129
        binder.registerCustomEditor(UuidList.class, new UUIDListPropertyEditor());
130
    }
131

    
132
    protected List<String> getDescriptionInfoInitStrategy(){
133
        return getInitializationStrategy();
134
    }
135

    
136
    /**
137
     * Runs the {@link DistributionAggregation} in a separate Thread and
138
     * responds with a redirect to a progress monitor REST service end point.
139
     * <p>
140
     *
141
     * @param mode
142
     *      one of <code>byAreas</code>, <code>byRanks</code>,
143
     *      <code>byAreasAndRanks</code>
144
     * @param frontendBaseUrl
145
     *      the cdm server instance base URL, this is needed for the a
146
     *      proper redirect URL when the service is running behind a
147
     *      reverse HTTP proxy
148
     * @param priority
149
     *      the priority for the Thread to spawn, see
150
     *      {@link Thread#setPriority(int)}, defaults to 3
151
     * @param targetAreaLevel
152
     *      The level of target areas to project the distributions to.
153
     * @param lowerRank
154
     * @param upperRank
155
     *
156
     * @param request
157
     * @param response
158
     * @return
159
     * @throws IOException
160
     */
161
    @RequestMapping(value = { "accumulateDistributions" }, method = RequestMethod.GET)
162
    public ModelAndView doAccumulateDistributions(
163
            @RequestParam(value= "mode", required = true) AggregationMode mode,
164
            @RequestParam(value= "mode2", required = true) AggregationMode mode2,
165
            @RequestParam(value = "targetAreaLevel", required = true) UUID targetAreaLevelUuid,
166
            @RequestParam(value = "frontendBaseUrl", required = false) String frontendBaseUrl,
167
            @RequestParam(value = "priority", required = false, defaultValue="3") Integer priority,
168
//            @RequestParam(value = "lowerRank", required = false) Rank lowerRank,
169
//            @RequestParam(value = "upperRank", required = false) Rank upperRank,
170
            @RequestParam(value = "minRank", required = false) UUID lowerRank,
171
            @RequestParam(value = "maxRank", required = false) UUID upperRank,
172
            @RequestParam(value = "subtrees", required = false) UuidList subtreeUuids,
173
            @RequestParam(value = "classifications", required = false) UuidList classificationUuids,
174
            @RequestParam(value = "taxa", required = false) UuidList taxonUuids,
175
            @RequestParam(value = "taxonnodes", required = false) UuidList taxonNodeUuids,
176
//            @RequestParam(value = "includeUnpublished", defaultValue="false") Boolean includeUnpublished,  //for now we do not allow unpublished data to be exported via webservice as long as read authentication is not implemented
177
//            @RequestParam(value = "area", required = false) UuidList areaUuids,
178
            HttpServletRequest request,
179
            HttpServletResponse response) throws IOException {
180

    
181
        logger.info("doAccumulateDistributions()" + request.getRequestURI());
182

    
183
        String processLabel = "accumulating distributions";
184

    
185
        ProgressMonitorUtil progressUtil = new ProgressMonitorUtil(progressMonitorController);
186

    
187
        final List<String> term_init_strategy = Arrays.asList(new String []{
188
                "representations"
189
        });
190
        NamedAreaLevel targetAreaLevel = (NamedAreaLevel)termService.load(targetAreaLevelUuid, term_init_strategy);
191

    
192
        if (!progressMonitorController.isMonitorRunning(transmissionEngineMonitorUuid)) {
193
            transmissionEngineMonitorUuid = progressUtil.registerNewMonitor();
194
            Thread subThread = new Thread() {
195
                @Override
196
                public void run() {
197
                    Pager<NamedArea> areaPager = termService.list(targetAreaLevel, (NamedAreaType) null,
198
                            null, null, (List<OrderHint>) null, term_init_strategy);
199
                    try {
200
                        TaxonNodeFilter filter = TaxonNodeFilter.NewInstance(classificationUuids, subtreeUuids,
201
                                taxonNodeUuids, taxonUuids, null, lowerRank, upperRank);
202
                        List<AggregationMode> modes = Arrays.asList(new AggregationMode[]{mode, mode2});
203
                        modes.remove(null);
204
                        List<UUID> areaUuids = new ArrayList<>();
205
                        areaPager.getRecords().forEach(p ->areaUuids.add(p.getUuid()));
206
                        DistributionAggregationConfiguration config = DistributionAggregationConfiguration.NewInstance(
207
                                modes, areaUuids, filter, progressMonitorController.getMonitor(transmissionEngineMonitorUuid));
208
                        DistributionAggregation distrAggr = new DistributionAggregation();
209
                        distrAggr.invoke(config, repository);
210
                    } catch (Exception e) {
211
                        IRestServiceProgressMonitor monitor = progressMonitorController.getMonitor(transmissionEngineMonitorUuid);
212
                        monitor.setIsFailed(true);
213
                        monitor.setFeedback(e);
214
                    }
215
                }
216
            };
217
            if(priority == null) {
218
                priority = AbstractController.DEFAULT_BATCH_THREAD_PRIORITY;
219
            }
220
            subThread.setPriority(priority);
221
            subThread.start();
222
        }
223

    
224
        // send redirect "see other"
225
        return progressUtil.respondWithMonitor(frontendBaseUrl, processLabel, transmissionEngineMonitorUuid, false, request, response);
226
    }
227

    
228
    @RequestMapping(value = "namedAreasInUse", method = RequestMethod.GET)
229
    public Pager<TermDto> doPageNamedAreasInUse(
230
            @RequestParam(value = "includeAllParents", required = false) boolean includeAllParents,
231
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
232
            @RequestParam(value = "pageIndex", required = false) Integer pageNumber, HttpServletRequest request,
233
            HttpServletResponse response) throws IOException {
234

    
235
        logger.info("doPageNamedAreasInUse : " + requestPathAndQuery(request));
236

    
237
        PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
238
        pagerParams.normalizeAndValidate(response);
239

    
240
        Pager<TermDto> pager = service.pageNamedAreasInUse(includeAllParents, pagerParams.getPageSize(), pagerParams.getPageIndex());
241

    
242
        localizeTerms(pager);
243

    
244
        return pager;
245
    }
246

    
247
    /**
248
     * @param taxonUuid
249
     * @param parts
250
     *            possible values: condensedStatus, tree, mapUriParams,
251
     *            elements,
252
     * @param subAreaPreference
253
     * @param statusOrderPreference
254
     * @param hideMarkedAreasList
255
     * @param omitLevels
256
     * @param request
257
     * @param response
258
     * @param distributionOrder
259
     *  Default is  LABEL
260
     * @param recipe
261
     *  The recipe for creating the condensed distribution status
262
     * @return
263
     * @throws IOException
264
     * @throws JsonMappingException
265
     * @throws JsonParseException
266
     */
267
    @RequestMapping(value = "distributionInfoFor/{uuid}", method = RequestMethod.GET)
268
    public ModelAndView doGetDistributionInfo(
269
            @PathVariable("uuid") UUID taxonUuid,
270
            @RequestParam("part") Set<InfoPart> partSet,
271
            @RequestParam(value = "subAreaPreference", required = false) boolean subAreaPreference,
272
            @RequestParam(value = "statusOrderPreference", required = false) boolean statusOrderPreference,
273
            @RequestParam(value = "hiddenAreaMarkerType", required = false) DefinedTermBaseList<MarkerType> hiddenAreaMarkerTypeList,
274
            @RequestParam(value = "omitLevels", required = false) Set<NamedAreaLevel> omitLevels,
275
            @RequestParam(value = "statusColors", required = false) String statusColorsString,
276
            @RequestParam(value = "distributionOrder", required = false, defaultValue="LABEL") DistributionOrder distributionOrder,
277
            @RequestParam(value = "recipe", required = false, defaultValue="EuroPlusMed") CondensedDistributionRecipe recipe,
278
            HttpServletRequest request,
279
            HttpServletResponse response) throws JsonParseException, JsonMappingException, IOException {
280

    
281
            logger.info("doGetDistributionInfo() - " + requestPathAndQuery(request));
282

    
283
            ModelAndView mv = new ModelAndView();
284

    
285
            boolean ignoreDistributionStatusUndefined = true;  //workaround until #9500 is fully implemented
286
            boolean fallbackAsParent = true;  //may become a service parameter in future
287

    
288
            DistributionInfoDTO dto;
289
            try {
290
                CondensedDistributionConfiguration condensedConfig = recipe.toConfiguration();
291
                //hiddenArea markers include markers for fully hidden areas and fallback areas. The later
292
                //are hidden markers on areas that have non-hidden subareas (#4408)
293
                Set<MarkerType> hiddenAreaMarkerTypes = null;
294
                if(hiddenAreaMarkerTypeList != null && !hiddenAreaMarkerTypeList.isEmpty()){
295
                    hiddenAreaMarkerTypes = hiddenAreaMarkerTypeList.asSet();
296
                    condensedConfig.hiddenAndFallbackAreaMarkers = hiddenAreaMarkerTypeList.stream().map(mt->mt.getUuid()).collect(Collectors.toSet());
297
                }
298

    
299
                EnumSet<InfoPart> parts = EnumSet.copyOf(partSet);
300

    
301
                Map<PresenceAbsenceTerm, Color> distributionStatusColors = EditGeoServiceUtilities.buildStatusColorMap(
302
                        statusColorsString, termService, vocabularyService);
303

    
304
                dto = geoService.composeDistributionInfoFor(parts, taxonUuid,
305
                        subAreaPreference, statusOrderPreference, hiddenAreaMarkerTypes, fallbackAsParent,
306
                        omitLevels, distributionStatusColors, LocaleContext.getLanguages(),
307
                        getDescriptionInfoInitStrategy(), condensedConfig, distributionOrder,
308
                        ignoreDistributionStatusUndefined);
309
                mv.addObject(dto);
310
                return mv;
311
            } catch (Exception e) {
312
                HttpStatusMessage.create("Exception when retrieving distribution info for " + taxonUuid, 500).send(response);
313
                return null;
314
            }
315
    }
316
}
(23-23/76)