2323import java .io .InputStreamReader ;
2424import java .nio .charset .StandardCharsets ;
2525import java .util .ArrayList ;
26+ import java .util .Arrays ;
27+ import java .util .Collections ;
28+ import java .util .HashMap ;
2629import java .util .HashSet ;
2730import java .util .LinkedHashMap ;
2831import java .util .List ;
4144import org .apache .hugegraph .driver .HugeClient ;
4245import org .apache .hugegraph .driver .SchemaManager ;
4346import org .apache .hugegraph .exception .ExternalException ;
47+ import org .apache .hugegraph .structure .constant .Cardinality ;
48+ import org .apache .hugegraph .structure .constant .DataType ;
49+ import org .apache .hugegraph .structure .constant .Frequency ;
50+ import org .apache .hugegraph .structure .constant .IdStrategy ;
51+ import org .apache .hugegraph .structure .schema .EdgeLabel ;
52+ import org .apache .hugegraph .structure .schema .PropertyKey ;
53+ import org .apache .hugegraph .structure .schema .VertexLabel ;
4454import org .apache .hugegraph .util .Ex ;
4555
4656@ RestController
@@ -152,8 +162,10 @@ public Map<String, Object> load(@PathVariable("graphspace") String graphSpace,
152162 Ex .check (loader || rank || hlm , "common.param.should-belong-to" ,
153163 "dataset" , "[loader, hlm, rank]" );
154164 HugeClient client = this .authGremlinClient (graphSpace , graph );
165+ SchemaManager schema = client .schema ();
166+ validateSchemaCompatibility (schema , dataset );
155167 try {
156- createSchema (client , dataset );
168+ createSchema (schema , dataset );
157169 String script = IDEMPOTENT_TRAVERSAL_FALLBACK_MARKER +
158170 data (dataset );
159171 client .gremlin ().gremlin (script ).execute ();
@@ -176,8 +188,7 @@ public Map<String, Object> load(@PathVariable("graphspace") String graphSpace,
176188 return result ;
177189 }
178190
179- private static void createSchema (HugeClient client , String dataset ) {
180- SchemaManager schema = client .schema ();
191+ private static void createSchema (SchemaManager schema , String dataset ) {
181192 Set <String > propertyKeys = new HashSet <>();
182193 schema .getPropertyKeys ().forEach (key -> propertyKeys .add (key .name ()));
183194 Set <String > vertexLabels = new HashSet <>();
@@ -193,6 +204,149 @@ private static void createSchema(HugeClient client, String dataset) {
193204 }
194205 }
195206
207+ private static void validateSchemaCompatibility (SchemaManager schema ,
208+ String dataset ) {
209+ Map <String , PropertyKey > propertyKeys = new HashMap <>();
210+ schema .getPropertyKeys ().forEach (key -> propertyKeys .put (key .name (), key ));
211+ Map <String , VertexLabel > vertexLabels = new HashMap <>();
212+ schema .getVertexLabels ().forEach (label ->
213+ vertexLabels .put (label .name (), label ));
214+ Map <String , EdgeLabel > edgeLabels = new HashMap <>();
215+ schema .getEdgeLabels ().forEach (label ->
216+ edgeLabels .put (label .name (), label ));
217+
218+ if ("loader" .equals (dataset )) {
219+ validateLoaderSchema (dataset , propertyKeys , vertexLabels , edgeLabels );
220+ } else if ("rank" .equals (dataset )) {
221+ validateRankSchema (dataset , propertyKeys , vertexLabels , edgeLabels );
222+ } else {
223+ validateHlmSchema (dataset , propertyKeys , vertexLabels , edgeLabels );
224+ }
225+ }
226+
227+ private static void validateLoaderSchema (
228+ String dataset , Map <String , PropertyKey > propertyKeys ,
229+ Map <String , VertexLabel > vertexLabels ,
230+ Map <String , EdgeLabel > edgeLabels ) {
231+ requireProperty (dataset , propertyKeys , "name" , DataType .TEXT );
232+ requireProperty (dataset , propertyKeys , "age" , DataType .INT );
233+ requireProperty (dataset , propertyKeys , "city" , DataType .TEXT );
234+ requireProperty (dataset , propertyKeys , "weight" , DataType .DOUBLE );
235+ requireProperty (dataset , propertyKeys , "lang" , DataType .TEXT );
236+ requireProperty (dataset , propertyKeys , "date" , DataType .TEXT );
237+ requireProperty (dataset , propertyKeys , "price" , DataType .DOUBLE );
238+ requireVertex (dataset , vertexLabels , "person" , IdStrategy .PRIMARY_KEY ,
239+ names ("name" , "age" , "city" ),
240+ Collections .singletonList ("name" ),
241+ names ("age" , "city" ));
242+ requireVertex (dataset , vertexLabels , "software" ,
243+ IdStrategy .CUSTOMIZE_NUMBER ,
244+ names ("name" , "lang" , "price" ),
245+ Collections .emptyList (), Collections .emptySet ());
246+ requireEdge (dataset , edgeLabels , "knows" , "person" , "person" ,
247+ names ("date" , "weight" ));
248+ requireEdge (dataset , edgeLabels , "created" , "person" , "software" ,
249+ names ("date" , "weight" ));
250+ }
251+
252+ private static void validateRankSchema (
253+ String dataset , Map <String , PropertyKey > propertyKeys ,
254+ Map <String , VertexLabel > vertexLabels ,
255+ Map <String , EdgeLabel > edgeLabels ) {
256+ requireProperty (dataset , propertyKeys , "name" , DataType .TEXT );
257+ requireVertex (dataset , vertexLabels , "person" ,
258+ IdStrategy .CUSTOMIZE_STRING ,
259+ names ("name" ), Collections .emptyList (),
260+ Collections .emptySet ());
261+ requireVertex (dataset , vertexLabels , "movie" ,
262+ IdStrategy .CUSTOMIZE_STRING ,
263+ names ("name" ), Collections .emptyList (),
264+ Collections .emptySet ());
265+ requireEdge (dataset , edgeLabels , "follow" , "person" , "person" ,
266+ Collections .emptySet ());
267+ requireEdge (dataset , edgeLabels , "like" , "person" , "movie" ,
268+ Collections .emptySet ());
269+ requireEdge (dataset , edgeLabels , "directedBy" , "movie" , "person" ,
270+ Collections .emptySet ());
271+ }
272+
273+ private static void validateHlmSchema (
274+ String dataset , Map <String , PropertyKey > propertyKeys ,
275+ Map <String , VertexLabel > vertexLabels ,
276+ Map <String , EdgeLabel > edgeLabels ) {
277+ requireProperty (dataset , propertyKeys , "name" , DataType .TEXT );
278+ requireProperty (dataset , propertyKeys , "gender" , DataType .TEXT );
279+ requireProperty (dataset , propertyKeys , "age" , DataType .INT );
280+ requireProperty (dataset , propertyKeys , "title" , DataType .TEXT );
281+ requireProperty (dataset , propertyKeys , "feature" , DataType .TEXT );
282+ requireProperty (dataset , propertyKeys , "intimacy" , DataType .TEXT );
283+ requireVertex (dataset , vertexLabels , "人物" , IdStrategy .PRIMARY_KEY ,
284+ names ("name" , "gender" , "age" , "title" , "feature" ),
285+ Collections .singletonList ("name" ),
286+ Collections .emptySet ());
287+ requireEdge (dataset , edgeLabels , "关系" , "人物" , "人物" ,
288+ names ("intimacy" ));
289+ }
290+
291+ private static void requireProperty (String dataset ,
292+ Map <String , PropertyKey > existing ,
293+ String name , DataType dataType ) {
294+ PropertyKey propertyKey = existing .get (name );
295+ if (propertyKey != null &&
296+ (propertyKey .dataType () != dataType ||
297+ propertyKey .cardinality () != Cardinality .SINGLE )) {
298+ incompatible (dataset , "property key" , name );
299+ }
300+ }
301+
302+ private static void requireVertex (String dataset ,
303+ Map <String , VertexLabel > existing ,
304+ String name , IdStrategy idStrategy ,
305+ Set <String > properties ,
306+ List <String > primaryKeys ,
307+ Set <String > nullableKeys ) {
308+ VertexLabel vertexLabel = existing .get (name );
309+ if (vertexLabel != null &&
310+ (vertexLabel .idStrategy () != idStrategy ||
311+ !vertexLabel .properties ().equals (properties ) ||
312+ !vertexLabel .primaryKeys ().equals (primaryKeys ) ||
313+ !vertexLabel .nullableKeys ().containsAll (nullableKeys ) ||
314+ !hasDefaultTtl (vertexLabel .ttl (), vertexLabel .ttlStartTime ()))) {
315+ incompatible (dataset , "vertex label" , name );
316+ }
317+ }
318+
319+ private static void requireEdge (String dataset ,
320+ Map <String , EdgeLabel > existing ,
321+ String name , String source , String target ,
322+ Set <String > properties ) {
323+ EdgeLabel edgeLabel = existing .get (name );
324+ Map <String , String > expectedLink = new HashMap <>();
325+ expectedLink .put (source , target );
326+ if (edgeLabel != null &&
327+ (!edgeLabel .properties ().equals (properties ) ||
328+ edgeLabel .links ().size () != 1 ||
329+ !edgeLabel .links ().contains (expectedLink ) ||
330+ edgeLabel .frequency () == Frequency .MULTIPLE ||
331+ !edgeLabel .sortKeys ().isEmpty () ||
332+ !hasDefaultTtl (edgeLabel .ttl (), edgeLabel .ttlStartTime ()))) {
333+ incompatible (dataset , "edge label" , name );
334+ }
335+ }
336+
337+ private static boolean hasDefaultTtl (long ttl , String ttlStartTime ) {
338+ return ttl == 0L && ttlStartTime == null ;
339+ }
340+
341+ private static Set <String > names (String ... values ) {
342+ return new HashSet <>(Arrays .asList (values ));
343+ }
344+
345+ private static void incompatible (String dataset , String type , String name ) {
346+ throw new ExternalException ("graph.sample.schema-incompatible" ,
347+ dataset , type , name );
348+ }
349+
196350 private static void createLoaderSchema (SchemaManager schema ,
197351 Set <String > propertyKeys ,
198352 Set <String > vertexLabels ,
0 commit comments