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.models;
21  
22  import com.tinkerpop.blueprints.Direction;
23  import com.tinkerpop.blueprints.Vertex;
24  import com.tinkerpop.frames.Adjacency;
25  import com.tinkerpop.frames.modules.javahandler.JavaHandler;
26  import com.tinkerpop.frames.modules.javahandler.JavaHandlerContext;
27  import com.tinkerpop.gremlin.java.GremlinPipeline;
28  import com.tinkerpop.pipes.util.Pipeline;
29  import eu.ehri.project.definitions.Ontology;
30  import eu.ehri.project.models.annotations.EntityType;
31  import eu.ehri.project.models.annotations.Fetch;
32  import eu.ehri.project.models.annotations.Meta;
33  import eu.ehri.project.models.base.AbstractUnit;
34  import eu.ehri.project.models.base.Accessor;
35  import eu.ehri.project.models.utils.JavaHandlerUtils;
36  
37  import static eu.ehri.project.models.utils.JavaHandlerUtils.addSingleRelationship;
38  import static eu.ehri.project.models.utils.JavaHandlerUtils.addUniqueRelationship;
39  import static eu.ehri.project.models.utils.JavaHandlerUtils.removeAllRelationships;
40  
41  /**
42   * Virtual documentary unit. Note: a *virtual* unit can
43   * have its own descriptions which do not refer to *actual*
44   * doc units, but are structurally the same. However, the label
45   * and direction is different in these cases, with the "purely
46   * virtual" descriptions having an outgoing "describes" relationship
47   * to the VU, whereas descriptions that describe real doc units have
48   * an incoming "isDescribedBy" relationship from a VU. The difference
49   * denotes ownership (dependency) which likewise controls cascading
50   * deletions.
51   */
52  @EntityType(EntityClass.VIRTUAL_UNIT)
53  public interface VirtualUnit extends AbstractUnit {
54  
55      @Meta(CHILD_COUNT)
56      @JavaHandler
57      int getChildCount();
58  
59      @Fetch(Ontology.VC_IS_PART_OF)
60      @Adjacency(label = Ontology.VC_IS_PART_OF)
61      VirtualUnit getParent();
62  
63      /**
64       * Add a child.
65       *
66       * @param child The child collection
67       * @return Whether or not the operation was allowed.
68       */
69      @JavaHandler
70      boolean addChild(VirtualUnit child);
71  
72      /**
73       * Remove a child virtual unit from this one.
74       *
75       * @param child a virtual unit frame
76       * @return whether or not the item was removed
77       */
78      @JavaHandler
79      boolean removeChild(VirtualUnit child);
80  
81      /*
82       * Fetches a list of all ancestors (parent -> parent -> parent)
83       */
84      @JavaHandler
85      Iterable<VirtualUnit> getAncestors();
86  
87      /**
88       * Get the child virtual units subordinate to this one.
89       *
90       * @return an iterable of virtual unit frames
91       */
92      @JavaHandler
93      Iterable<VirtualUnit> getChildren();
94  
95      /**
96       * Fetch <b>all</b> child virtual units and their children
97       * recursively.
98       *
99       * @return an iterable of virtual unit frames
100      */
101     @JavaHandler
102     Iterable<VirtualUnit> getAllChildren();
103 
104     /**
105      * Fetch documentary unit items included in this virtual unit.
106      *
107      * @return an iterable of documentary unit frames
108      */
109     @Fetch(value = Ontology.VC_INCLUDES_UNIT, full = true)
110     @Adjacency(label = Ontology.VC_INCLUDES_UNIT, direction = Direction.OUT)
111     Iterable<DocumentaryUnit> getIncludedUnits();
112 
113     /**
114      * Get the repositories which hold the documentary unit items
115      * included in this virtual unit.
116      *
117      * @return an iterable of repository frames
118      */
119     @JavaHandler
120     Iterable<Repository> getRepositories();
121 
122     /**
123      * Add a documentary unit to be included in this virtual unit.
124      *
125      * @param unit a documentary unit frame
126      * @return whether or not the item was newly added
127      */
128     @JavaHandler
129     boolean addIncludedUnit(DocumentaryUnit unit);
130 
131     /**
132      * Remove a documentary unit item from this virtual unit.
133      *
134      * @param unit a documentary unit frame
135      */
136     @JavaHandler
137     void removeIncludedUnit(DocumentaryUnit unit);
138 
139     /**
140      * Fetch the author of this virtual unit.
141      *
142      * @return a user or group frame
143      */
144     @Fetch(value = Ontology.VC_HAS_AUTHOR, numLevels = 0)
145     @Adjacency(label = Ontology.VC_HAS_AUTHOR, direction = Direction.OUT)
146     Accessor getAuthor();
147 
148     /**
149      * Set the author of this virtual unit.
150      *
151      * @param accessor a user or group frame
152      */
153     @JavaHandler
154     void setAuthor(Accessor accessor);
155 
156     /**
157      * Fetch the descriptions of this virtual unit.
158      *
159      * @return an iterable of documentary unit description frames
160      */
161     @Adjacency(label = Ontology.DESCRIPTION_FOR_ENTITY, direction = Direction.IN)
162     Iterable<DocumentaryUnitDescription> getVirtualDescriptions();
163 
164     /**
165      * Implementation of complex methods.
166      */
167     abstract class Impl implements JavaHandlerContext<Vertex>, VirtualUnit {
168 
169         @Override
170         public void setAuthor(Accessor accessor) {
171             addSingleRelationship(it(), accessor.asVertex(), Ontology.VC_HAS_AUTHOR);
172         }
173 
174         @Override
175         public void removeIncludedUnit(DocumentaryUnit unit) {
176             removeAllRelationships(it(), unit.asVertex(), Ontology.VC_INCLUDES_UNIT);
177         }
178 
179         @Override
180         public Iterable<VirtualUnit> getChildren() {
181             return frameVertices(gremlin().in(Ontology.VC_IS_PART_OF));
182         }
183 
184         @Override
185         public boolean addChild(VirtualUnit child) {
186             if (child.asVertex().equals(it())) {
187                 // Self-referential.
188                 return false;
189             }
190             for (Vertex parent : traverseAncestors()) {
191                 if (child.asVertex().equals(parent)) {
192                     // Loop
193                     return false;
194                 }
195             }
196 
197             return addUniqueRelationship(child.asVertex(), it(), Ontology.VC_IS_PART_OF);
198         }
199 
200         @Override
201         public boolean removeChild(VirtualUnit child) {
202             return removeAllRelationships(child.asVertex(), it(), Ontology.VC_IS_PART_OF);
203         }
204 
205         private GremlinPipeline<Vertex, Vertex> traverseAncestors() {
206             return gremlin().as("n")
207                     .out(Ontology.VC_IS_PART_OF)
208                     .loop("n", JavaHandlerUtils.defaultMaxLoops, JavaHandlerUtils.noopLoopFunc);
209         }
210 
211         @Override
212         public Iterable<VirtualUnit> getAllChildren() {
213             Pipeline<Vertex, Vertex> otherPipe = gremlin().as("n").in(Ontology.VC_IS_PART_OF)
214                     .loop("n", JavaHandlerUtils.noopLoopFunc, JavaHandlerUtils.noopLoopFunc);
215 
216             return frameVertices(gremlin().in(Ontology.VC_IS_PART_OF).cast(Vertex.class).copySplit(gremlin(), otherPipe)
217                     .fairMerge().cast(Vertex.class));
218         }
219 
220         @Override
221         public Iterable<VirtualUnit> getAncestors() {
222             return frameVertices(traverseAncestors());
223         }
224 
225         @Override
226         public boolean addIncludedUnit(DocumentaryUnit unit) {
227             return addUniqueRelationship(it(), unit.asVertex(), Ontology.VC_INCLUDES_UNIT);
228         }
229 
230         @Override
231         public int getChildCount() {
232             long incCount = gremlin().outE(Ontology.VC_INCLUDES_UNIT).count();
233             long vcCount = gremlin().inE(Ontology.VC_IS_PART_OF).count();
234             return Math.toIntExact(incCount + vcCount);
235         }
236     }
237 }