View Javadoc

1   /*
2    * Copyright 2015 Data Archiving and Networked Services (an institute of
3    * Koninklijke Nederlandse Akademie van Wetenschappen), King's College London,
4    * Georg-August-Universitaet Goettingen Stiftung Oeffentlichen Rechts
5    *
6    * Licensed under the EUPL, Version 1.1 or – as soon they will be approved by
7    * the European Commission - subsequent versions of the EUPL (the "Licence");
8    * You may not use this work except in compliance with the Licence.
9    * You may obtain a copy of the Licence at:
10   *
11   * https://joinup.ec.europa.eu/software/page/eupl
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the Licence is distributed on an "AS IS" basis,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the Licence for the specific language governing
17   * permissions and limitations under the Licence.
18   */
19  
20  package eu.ehri.project.commands;
21  
22  import com.tinkerpop.frames.FramedGraph;
23  import eu.ehri.project.acl.SystemScope;
24  import eu.ehri.project.core.GraphManager;
25  import eu.ehri.project.core.GraphManagerFactory;
26  import eu.ehri.project.exceptions.DeserializationError;
27  import eu.ehri.project.exceptions.ItemNotFound;
28  import eu.ehri.project.exceptions.PermissionDenied;
29  import eu.ehri.project.exceptions.ValidationError;
30  import eu.ehri.project.models.EntityClass;
31  import eu.ehri.project.models.UserProfile;
32  import eu.ehri.project.models.base.Accessible;
33  import eu.ehri.project.models.base.PermissionScope;
34  import eu.ehri.project.persistence.Bundle;
35  import eu.ehri.project.api.Api;
36  import org.apache.commons.cli.CommandLine;
37  import org.apache.commons.cli.Option;
38  import org.apache.commons.cli.Options;
39  
40  import java.util.Properties;
41  
42  /**
43   * Add a user.
44   */
45  public class EntityAdd extends BaseCommand {
46  
47      final static String NAME = "add";
48  
49      @Override
50      protected void setCustomOptions(Options options) {
51          options.addOption(Option.builder("P")
52                  .argName("property=value")
53                  .numberOfArgs(2)
54                  .valueSeparator()
55                  .desc("Add a property with the given value")
56                  .build());
57          options.addOption(Option.builder()
58                  .longOpt("user")
59                  .hasArg()
60                  .required()
61                  .type(String.class)
62                  .hasArg().desc("Identifier of user taking action")
63                  .build());
64          options.addOption(Option.builder()
65                  .longOpt("log")
66                  .hasArg()
67                  .type(String.class)
68                  .desc("Log message for delete action.")
69                  .build());
70          options.addOption(Option.builder()
71                  .longOpt("scope")
72                  .hasArg()
73                  .type(String.class)
74                  .desc("Identifier of scope to import into, i.e. repository")
75                  .build());
76          options.addOption(Option.builder()
77                  .longOpt("update")
78                  .desc("Update item if it already exists")
79                  .build());
80      }
81  
82      @Override
83      public String getUsage() {
84          return String.format("%s <type> [OPTIONS] [-Pkey=value]", NAME);
85      }
86  
87      @Override
88      public String getHelp() {
89          return "Create a new entity with the given id and properties";
90      }
91  
92      @Override
93      public int execWithOptions(FramedGraph<?> graph,
94              CommandLine cmdLine) throws ItemNotFound, ValidationError, PermissionDenied, DeserializationError {
95  
96          GraphManager manager = GraphManagerFactory.getInstance(graph);
97  
98          if (cmdLine.getArgList().size() < 1)
99              throw new RuntimeException(getUsage());
100 
101         String logMessage = "Imported from command-line";
102         if (cmdLine.hasOption("log")) {
103             logMessage = cmdLine.getOptionValue("log");
104         }
105 
106         // Find the agent
107         PermissionScope scope = SystemScope.getInstance();
108         if (cmdLine.hasOption("scope")) {
109             scope = manager.getEntity(cmdLine.getOptionValue("scope"), PermissionScope.class);
110         }
111 
112         // Find the user
113         UserProfile user = manager.getEntity(cmdLine.getOptionValue("user"),
114                 UserProfile.class);
115 
116         String typeName = cmdLine.getArgList().get(0);
117         EntityClass entityClass = EntityClass.withName(typeName);
118         Properties properties = cmdLine.getOptionProperties("P");
119 
120         Bundle.Builder builder = Bundle.Builder.withClass(entityClass);
121         for (Object prop : properties.keySet()) {
122             builder.addDataValue((String) prop, properties.getProperty((String) prop));
123         }
124         Bundle bundle = builder.build();
125         String id = entityClass.getIdGen().generateId(scope.idPath(), bundle);
126 
127         try {
128             createItem(graph, cmdLine, id, bundle, scope, user, logMessage);
129         } catch (ValidationError e) {
130             System.err.printf("A user a id: '%s' already exists%n", id);
131             return CmdEntryPoint.RetCode.BAD_DATA.getCode();
132         } catch (PermissionDenied e) {
133             System.err.printf("User %s does not have permission to perform that action.%n", user.getId());
134             return CmdEntryPoint.RetCode.BAD_PERMS.getCode();
135         } catch (DeserializationError e) {
136             System.err.println(e.getMessage());
137             return CmdEntryPoint.RetCode.BAD_DATA.getCode();
138         }
139 
140         return 0;
141     }
142 
143     // Suppressing warnings here because we throw a RuntimeException if the
144     // item class is not of an acceptable type.
145     public void createItem(FramedGraph<?> graph,
146             CommandLine cmdLine, String id, Bundle bundle,
147             PermissionScope scope, UserProfile user, String logMessage) throws DeserializationError,
148             ValidationError, PermissionDenied {
149 
150         Class<?> cls = bundle.getBundleJavaClass();
151         if (!Accessible.class.isAssignableFrom(cls)) {
152             throw new DeserializationError("Item class: " + cls.getSimpleName() +
153                     " is not a first-class database item");
154         }
155         @SuppressWarnings("unchecked")
156         Class<? extends Accessible> accessibleCls = (Class<? extends Accessible>) cls;
157 
158         Api api = api(graph, user);
159         if (cmdLine.hasOption("update")) {
160             api.createOrUpdate(bundle.withId(id), accessibleCls, getLogMessage(logMessage));
161         } else {
162             api.create(bundle.withId(id), accessibleCls, getLogMessage(logMessage));
163         }
164     }
165 }