View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.graphql.command;
23  
24  import org.opencastproject.authorization.xacml.manager.api.AclService;
25  import org.opencastproject.authorization.xacml.manager.api.AclServiceFactory;
26  import org.opencastproject.elasticsearch.api.SearchIndexException;
27  import org.opencastproject.elasticsearch.index.ElasticsearchIndex;
28  import org.opencastproject.graphql.exception.GraphQLRuntimeException;
29  import org.opencastproject.graphql.execution.context.OpencastContext;
30  import org.opencastproject.graphql.execution.context.OpencastContextManager;
31  import org.opencastproject.graphql.series.GqlSeries;
32  import org.opencastproject.graphql.type.input.AccessControlListInput;
33  import org.opencastproject.graphql.type.input.GqlCommonSeriesMetadataInput;
34  import org.opencastproject.index.service.api.IndexService;
35  import org.opencastproject.index.service.catalog.adapter.series.CommonSeriesCatalogUIAdapter;
36  import org.opencastproject.index.service.exception.IndexServiceException;
37  import org.opencastproject.mediapackage.MediaPackageElementFlavor;
38  import org.opencastproject.metadata.dublincore.DublinCoreMetadataCollection;
39  import org.opencastproject.metadata.dublincore.MetadataField;
40  import org.opencastproject.metadata.dublincore.MetadataList;
41  import org.opencastproject.security.api.AccessControlEntry;
42  import org.opencastproject.security.api.AccessControlList;
43  import org.opencastproject.security.api.SecurityService;
44  import org.opencastproject.series.api.SeriesService;
45  
46  import com.entwinemedia.fn.data.Opt;
47  
48  import java.util.Map;
49  import java.util.TreeMap;
50  
51  public class CreateSeriesCommand extends AbstractCommand<GqlSeries> {
52  
53    private AccessControlListInput aclInput;
54  
55    public CreateSeriesCommand(final Builder builder) {
56      super(builder);
57      this.aclInput = builder.accessControlListInput;
58    }
59  
60    @Override
61    public GqlSeries execute() {
62      OpencastContext context = OpencastContextManager.getCurrentContext();
63      final ElasticsearchIndex index = context.getService(ElasticsearchIndex.class);
64      final IndexService indexService = context.getService(IndexService.class);
65  
66      final Map<String, Object> seriesMetadata = environment.getArgument("metadata");
67  
68      MetadataList metadataList = createMetadataList(seriesMetadata, indexService);
69      Map<String, String> options = new TreeMap<>();
70      Opt<Long> optThemeId = Opt.none();
71  
72      final SeriesService seriesService = context.getService(SeriesService.class);
73  
74      AccessControlList acl = new AccessControlList();
75      for (var entry : aclInput.getEntries()) {
76        for (var action : entry.getAction()) {
77          acl.getEntries().add(new AccessControlEntry(entry.getRole(), action, true));
78        }
79      }
80  
81      if (aclInput.getManagedAclId() != null) {
82        AclService aclService = context.getService(AclServiceFactory.class)
83            .serviceFor(context.getService(SecurityService.class).getOrganization());
84        aclService.getAcl(aclInput.getManagedAclId())
85            .ifPresent(value -> acl.merge(value.getAcl()));
86      }
87      String seriesId;
88      try {
89        seriesId = indexService.createSeries(metadataList, options, Opt.some(acl), optThemeId);
90      } catch (IndexServiceException e) {
91        throw new GraphQLRuntimeException(e);
92      }
93  
94      try {
95        return new GqlSeries(
96            index.getSeries(seriesId, context.getOrganization().getId(), context.getUser()).get()
97        );
98      } catch (SearchIndexException e) {
99        throw new GraphQLRuntimeException(e);
100     }
101   }
102 
103   private MetadataList createMetadataList(Map<String, Object> seriesMetadata, IndexService indexService) {
104     CommonSeriesCatalogUIAdapter adapter = (CommonSeriesCatalogUIAdapter) indexService
105         .getCommonSeriesCatalogUIAdapter();
106 
107     MetadataList list = new MetadataList();
108     list.add(adapter, adapter.getRawFields());
109 
110     final MediaPackageElementFlavor flavor = MediaPackageElementFlavor
111         .parseFlavor("dublincore/series");
112 
113     final DublinCoreMetadataCollection collection = list.getMetadataByFlavor(flavor.toString());
114 
115     seriesMetadata.keySet().forEach(k -> {
116       final MetadataField target = collection.getOutputFields().get(k);
117       target.setValue(seriesMetadata.get(k));
118     });
119 
120     return list;
121   }
122 
123   public static Builder create(
124       GqlCommonSeriesMetadataInput seriesMetadataInput,
125       AccessControlListInput accessControlListInput
126   ) {
127     return new Builder(seriesMetadataInput, accessControlListInput);
128   }
129 
130   public static class Builder extends AbstractCommand.Builder<GqlSeries> {
131 
132     private final GqlCommonSeriesMetadataInput seriesMetadataInput;
133 
134     private final AccessControlListInput accessControlListInput;
135 
136     public Builder(GqlCommonSeriesMetadataInput seriesMetadataInput, AccessControlListInput accessControlListInput) {
137       this.seriesMetadataInput = seriesMetadataInput;
138       this.accessControlListInput = accessControlListInput;
139     }
140 
141     @Override
142     public void validate() {
143       super.validate();
144       if (seriesMetadataInput == null) {
145         throw new IllegalStateException("Series metadata cannot be null");
146       }
147       if (accessControlListInput == null) {
148         throw new IllegalStateException("Access control list cannot be null");
149       }
150     }
151 
152     @Override
153     public CreateSeriesCommand build() {
154       validate();
155       return new CreateSeriesCommand(this);
156     }
157   }
158 
159 }