All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coursera.courier.api.ClassTemplateSpecs Maven / Gradle / Ivy

/*
 * Copyright 2015 Coursera Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.coursera.courier.api;

import com.linkedin.data.schema.DataSchema;
import com.linkedin.data.schema.NamedDataSchema;
import com.linkedin.data.schema.TyperefDataSchema;
import com.linkedin.pegasus.generator.spec.ArrayTemplateSpec;
import com.linkedin.pegasus.generator.spec.ClassTemplateSpec;
import com.linkedin.pegasus.generator.spec.CustomInfoSpec;
import com.linkedin.pegasus.generator.spec.MapTemplateSpec;
import com.linkedin.pegasus.generator.spec.RecordTemplateSpec;
import com.linkedin.pegasus.generator.spec.TyperefTemplateSpec;
import com.linkedin.pegasus.generator.spec.UnionTemplateSpec;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Utilities for ClassTemplateSpec.
 */
public class ClassTemplateSpecs {

  public static Set directReferencedTypes(ClassTemplateSpec spec) {
    Set results = new HashSet();
    if (spec instanceof RecordTemplateSpec) {
      RecordTemplateSpec recordSpec = (RecordTemplateSpec)spec;
      for (RecordTemplateSpec.Field field: recordSpec.getFields()) {
        results.add(field.getType());
      }
    } else if (spec instanceof UnionTemplateSpec) {
      UnionTemplateSpec unionSpec = (UnionTemplateSpec)spec;
      for (UnionTemplateSpec.Member member: unionSpec.getMembers()) {
        results.add(member.getClassTemplateSpec());
      }
    } else if (spec instanceof CourierMapTemplateSpec) {
      CourierMapTemplateSpec mapSpec = (CourierMapTemplateSpec)spec;
      if (mapSpec.getKeyClass() != null) {
        results.add(mapSpec.getKeyClass());
      }
      results.add(mapSpec.getValueClass());
    } else if (spec instanceof ArrayTemplateSpec) {
      ArrayTemplateSpec arraySpec = (ArrayTemplateSpec)spec;
      results.add(arraySpec.getItemClass());
    }
    return results;
  }

  public static CustomInfoSpec getImmediateCustomInfo(DataSchema schema, String customTypeLanguage)
  {
    CustomInfoSpec immediate = null;
    for (DataSchema current = schema; current != null; current = dereferenceIfTyperef(current))
    {
      final CourierTemplateSpecGenerator.CustomClasses customClasses =
          CourierTemplateSpecGenerator.getCustomClasses(current, customTypeLanguage);
      if (customClasses != null)
      {
        immediate = new CustomInfoSpec(
            (NamedDataSchema) schema,
            (NamedDataSchema) current,
            customClasses.customClass,
            customClasses.customCoercerClass);
        break;
      }
    }
    return immediate;
  }

  private static DataSchema dereferenceIfTyperef(DataSchema schema)
  {
    final DataSchema.Type type = schema.getType();
    return type == DataSchema.Type.TYPEREF ? ((TyperefDataSchema) schema).getRef() : null;
  }

  public static Set directContainedTypes(ClassTemplateSpec spec) {
    Set results = new HashSet();
    for (ClassTemplateSpec nested: directReferencedTypes(spec)) {
      if (nested.getEnclosingClass() == spec) {
        results.add(nested);
      }
    }
    return results;
  }

  public static Set allContainedTypes(ClassTemplateSpec spec) {
    Set results = new HashSet();
    for (ClassTemplateSpec nested: allReferencedTypes(spec)) {
      if (nested.getEnclosingClass() == spec) {
        results.add(nested);
      }
    }
    return results;
  }

  /**
   * Return all types directly or transitively referenced by this type.
   */
  public static Set allReferencedTypes(ClassTemplateSpec spec) {
    return findAllReferencedTypes(
        directReferencedTypes(spec),
        Collections.emptySet(),
        Collections.emptySet());
  }

  // traverses the directReferencedTypes graph, keeping track of already visited ClassTemplateSpecs
  private static Set findAllReferencedTypes(
      Set current,
      Set visited,
      Set acc) {

    //val nextUnvisited = current.flatMap(_.directReferencedTypes).filterNot(visited.contains);
    Set nextUnvisited = new HashSet();
    for (ClassTemplateSpec currentSpec: current) {
      for (ClassTemplateSpec maybeNext: directReferencedTypes(currentSpec)) {
        if (!visited.contains(maybeNext)) {
          nextUnvisited.add(maybeNext);
        }
      }
    }

    Set accAndCurrent = new HashSet(acc);
    accAndCurrent.addAll(current);

    if (nextUnvisited.size() > 0) {
      Set currentAndVisited = new HashSet(current);
      currentAndVisited.addAll(visited);

      return findAllReferencedTypes(nextUnvisited, currentAndVisited, accAndCurrent);
    } else {
      return accAndCurrent;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy