Clover icon

Magnolia REST Integration 2.1

  1. Project Clover database Fri Mar 16 2018 18:18:02 CET
  2. Package info.magnolia.rest.registry

File EndpointDefinitionRegistry.java

 

Coverage histogram

../../../../img/srcFileCovDistChart7.png
41% of files have more coverage

Code metrics

6
44
15
2
252
164
21
0.48
2.93
7.5
1.4
3% of code in this file is excluded from these metrics.

Classes

Class Line # Actions
EndpointDefinitionRegistry 69 43 3.1% 20 20
0.682539768.3%
EndpointDefinitionRegistry.RelativePathMetadataBuilder 246 1 0% 1 2
0.00%
 

Contributing tests

This file is covered by 9 tests. .

Source view

1    /**
2    * This file Copyright (c) 2013-2018 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.rest.registry;
35   
36    import static info.magnolia.rest.registry.EndpointDefinitionRegistryEventType.*;
37   
38    import info.magnolia.config.registry.AbstractRegistry;
39    import info.magnolia.config.registry.DefinitionMetadata;
40    import info.magnolia.config.registry.DefinitionMetadataBuilder;
41    import info.magnolia.config.registry.DefinitionProvider;
42    import info.magnolia.config.registry.DefinitionProvider.Problem;
43    import info.magnolia.config.registry.DefinitionType;
44    import info.magnolia.config.registry.decoration.DefinitionDecorator;
45    import info.magnolia.event.EventBus;
46    import info.magnolia.event.SystemEventBus;
47    import info.magnolia.module.ModuleRegistry;
48    import info.magnolia.objectfactory.Components;
49    import info.magnolia.registry.RegistrationException;
50    import info.magnolia.rest.DynamicPath;
51    import info.magnolia.rest.EndpointDefinition;
52   
53    import java.util.Collection;
54    import java.util.List;
55    import java.util.Optional;
56    import java.util.Set;
57   
58    import javax.inject.Inject;
59    import javax.inject.Named;
60    import javax.inject.Singleton;
61   
62    import org.slf4j.Logger;
63    import org.slf4j.LoggerFactory;
64   
65    /**
66    * Registry for {@linkplain EndpointDefinition REST endpoint definitions}.
67    */
68    @Singleton
 
69    public class EndpointDefinitionRegistry extends AbstractRegistry<EndpointDefinition> {
70   
71    private static final Logger log = LoggerFactory.getLogger(EndpointDefinitionRegistry.class);
72   
73    static final DefinitionType TYPE = new DefinitionType() {
 
74  6 toggle @Override
75    public String name() {
76  6 return "restEndpoint";
77    }
78   
 
79  0 toggle @Override
80    public Class baseClass() {
81  0 return EndpointDefinition.class;
82    }
83    };
84   
85    private EventBus systemEventBus;
86   
 
87  14 toggle @Inject
88    public EndpointDefinitionRegistry(ModuleRegistry moduleRegistry, @Named(SystemEventBus.NAME) EventBus systemEventBus) {
89  14 super(moduleRegistry);
90  14 this.systemEventBus = systemEventBus;
91    }
92   
93    /**
94    * @deprecated since 2.0 use {@link #EndpointDefinitionRegistry(ModuleRegistry, EventBus)} instead.
95    */
 
96  0 toggle @Deprecated
97    public EndpointDefinitionRegistry(@Named(SystemEventBus.NAME) EventBus systemEventBus) {
98  0 this(Components.getComponent(ModuleRegistry.class), systemEventBus);
99    }
100   
 
101  0 toggle @Override
102    public DefinitionType type() {
103  0 return TYPE;
104    }
105   
 
106  0 toggle @Override
107    public DefinitionMetadataBuilder newMetadataBuilder() {
108  0 return new RelativePathMetadataBuilder();
109    }
110   
 
111  45 toggle @Override
112    public void register(DefinitionProvider<EndpointDefinition> provider) {
113  45 DefinitionMetadata registeredMetadata = getRegistryMap().put(onRegister(provider));
114  45 if (registeredMetadata != null) {
115  44 DefinitionProvider<EndpointDefinition> decoratedProvider = getDecoratedDefinitionProvider(provider);
116  44 systemEventBus.fireEvent(new EndpointDefinitionRegistryEvent(REGISTERED, decoratedProvider));
117    }
118    }
119   
 
120  46 toggle @Override
121    protected DefinitionProvider<EndpointDefinition> onRegister(DefinitionProvider<EndpointDefinition> provider) {
122   
123  46 DefinitionProvider<EndpointDefinition> definitionProvider = super.onRegister(provider);
124   
125  46 try {
126  46 final EndpointDefinition endpointDefinition = provider.get();
127  46 DefinitionProvider<EndpointDefinition> conflictDefinition = getAllProviders().stream()
128    .filter(p -> !p.getMetadata().getReferenceId().equals(provider.getMetadata().getReferenceId()))
129    .filter(p -> endpointDefinition.getImplementationClass().getAnnotation(DynamicPath.class) == null)
130    .filter(p -> endpointDefinition.getImplementationClass().equals(p.get().getImplementationClass()))
131    .findFirst().orElse(null);
132   
133  32 if (conflictDefinition != null) {
134  1 final String message = String.format("Endpoint definitions [%s:%s] and [%s:%s] both declare implementationClass [%s]. REST module V1 does not support endpoints with identical implementationClass.",
135    provider.getMetadata().getName(),
136    provider.getMetadata().getReferenceId(),
137    conflictDefinition.getMetadata().getName(),
138    conflictDefinition.getMetadata().getReferenceId(),
139    endpointDefinition.getImplementationClass());
140  1 Problem problem = Problem.major()
141    .withDetails(message)
142    .withTitle("Conflict endpoint definitions.")
143    .withType(Problem.DefaultTypes.SEMANTIC)
144    .withLocation(provider.getMetadata().getLocation())
145    .build();
146  1 provider.getProblems().add(problem);
147    }
148    } catch (Exception e) {
149  14 log.error("Error happens when checking endpoint duplications.", e);
150    }
151  46 return definitionProvider;
152    }
153   
 
154  3 toggle @Override
155    public Set<DefinitionMetadata> unregisterAndRegister(Collection<DefinitionMetadata> toRemoveIds, Collection<DefinitionProvider<EndpointDefinition>> definitionProviders) {
156  3 Set<DefinitionMetadata> registeredIds = super.unregisterAndRegister(toRemoveIds, definitionProviders);
157   
158  3 toRemoveIds.stream()
159    .filter(metadata -> !registeredIds.contains(metadata))
160    .map(DefinitionMetadata::getReferenceId)
161    .forEach(referenceId -> systemEventBus.fireEvent(new EndpointDefinitionRegistryEvent(UNREGISTERED, referenceId)));
162   
163  3 definitionProviders.stream()
164    .filter(provider -> toRemoveIds.contains(provider.getMetadata()))
165    .filter(provider -> registeredIds.contains(provider.getMetadata()))
166    .forEach(provider -> systemEventBus.fireEvent(new EndpointDefinitionRegistryEvent(REREGISTERED, provider)));
167   
168  3 definitionProviders.stream()
169    .filter(provider -> !toRemoveIds.contains(provider.getMetadata()))
170    .filter(provider -> registeredIds.contains(provider.getMetadata()))
171    .forEach(provider -> systemEventBus.fireEvent(new EndpointDefinitionRegistryEvent(REGISTERED, provider)));
172   
173  3 return registeredIds;
174    }
175   
 
176  2 toggle @Override
177    public void addDecorator(DefinitionDecorator<EndpointDefinition> decorator) {
178  2 super.addDecorator(decorator);
179  2 Optional<DefinitionProvider<EndpointDefinition>> targetProvider = getAllProviders().stream()
180    .filter(decorator::appliesTo)
181    .findFirst();
182  2 if (targetProvider.isPresent()) {
183  2 systemEventBus.fireEvent(new EndpointDefinitionRegistryEvent(REREGISTERED, targetProvider.get()));
184    } else {
185    //provided decorator cannot be applied to any provider.
186  0 super.removeDecorator(decorator);
187    }
188    }
189   
 
190  0 toggle @Override
191    public void removeDecorator(DefinitionDecorator<EndpointDefinition> decorator) {
192  0 Optional<DefinitionProvider<EndpointDefinition>> targetProvider = getAllProviders().stream()
193    .filter(decorator::appliesTo)
194    .findFirst();
195  0 super.removeDecorator(decorator);
196  0 targetProvider.ifPresent(provider -> systemEventBus.fireEvent(new EndpointDefinitionRegistryEvent(REREGISTERED, provider)));
197    }
198   
199    /**
200    * @deprecated since 2.0 use {@link #getProvider(String)} instead.
201    */
 
202  2 toggle @Deprecated
203    public EndpointDefinition getEndpointDefinition(String name) throws RegistrationException {
204  2 final EndpointDefinition endpointDefinition;
205  2 try {
206  2 endpointDefinition = getProvider(name).get();
207    } catch (NoSuchDefinitionException | InvalidDefinitionException e) {
208  1 throw new RegistrationException(e.getMessage(), e);
209    }
210  1 return endpointDefinition;
211    }
212   
213    /**
214    * @deprecated since 2.0 use {@link #unregisterAndRegister(Collection, Collection)} instead.
215    */
 
216  0 toggle @Deprecated
217    public Set<String> unregisterAndRegister(Set<String> registeredNames, List<EndpointDefinitionProvider> providers) {
218  0 return null;
219    }
220   
221    /**
222    * @deprecated since 2.0 use standard registry APIs instead ({@link #getProvider(String)} and {@link DefinitionProvider#isValid()}).
223    */
 
224  0 toggle @Deprecated
225    public boolean isEndpointDefinitionRegistered(String name) {
226  0 try {
227  0 return getProvider(name).isValid();
228    } catch (NoSuchDefinitionException e) {
229  0 return false;
230    }
231    }
232   
233    /**
234    * @deprecated since 2.0 use {@link #getAllDefinitions()} instead.
235    */
 
236    toggle @Deprecated
237    public Collection<EndpointDefinition> getAllEndpointDefinitions() {
238    return getAllDefinitions();
239    }
240   
241    /**
242    * This DefinitionMetadataBuilder generates referenceId from the relative-location only.
243    * <p>This way, resource paths are dynamically configured/deduced from config path;
244    * and the {@link info.magnolia.rest.RestDispatcherServlet RestDispatcherServlet} is responsible for the routing.
245    */
 
246    public static class RelativePathMetadataBuilder extends DefinitionMetadataBuilder {
 
247  0 toggle @Override
248    protected String buildReferenceId() {
249  0 return getRelativeLocation();
250    }
251    }
252    }