You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apex.apache.org by ch...@apache.org on 2015/09/10 00:13:02 UTC

[31/50] incubator-apex-core git commit: SPOI-5338 #resolve cleanup of operator discoverer class to replace reflection with ASM Addressed review comments

SPOI-5338 #resolve cleanup of operator discoverer class to replace reflection with ASM
Addressed review comments


Project: http://git-wip-us.apache.org/repos/asf/incubator-apex-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-apex-core/commit/ba46e71f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-apex-core/tree/ba46e71f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-apex-core/diff/ba46e71f

Branch: refs/heads/master
Commit: ba46e71f5744e4e822d0f11a35e00b28ee91edb9
Parents: fe5d035
Author: ishark <is...@datatorrent.com>
Authored: Tue Jul 7 16:40:23 2015 -0700
Committer: ishark <is...@datatorrent.com>
Committed: Thu Aug 13 14:38:12 2015 -0700

----------------------------------------------------------------------
 .../java/com/datatorrent/stram/cli/DTCli.java   |  18 +-
 .../stram/webapp/OperatorDiscoverer.java        | 204 +++++++++----------
 .../stram/webapp/StramWebServices.java          |   8 +-
 .../com/datatorrent/stram/webapp/TypeGraph.java |  86 ++++++--
 .../stram/webapp/OperatorDiscoveryTest.java     |   9 +-
 5 files changed, 175 insertions(+), 150 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-apex-core/blob/ba46e71f/engine/src/main/java/com/datatorrent/stram/cli/DTCli.java
----------------------------------------------------------------------
diff --git a/engine/src/main/java/com/datatorrent/stram/cli/DTCli.java b/engine/src/main/java/com/datatorrent/stram/cli/DTCli.java
index eff2404..ff6e84c 100644
--- a/engine/src/main/java/com/datatorrent/stram/cli/DTCli.java
+++ b/engine/src/main/java/com/datatorrent/stram/cli/DTCli.java
@@ -86,7 +86,6 @@ import com.datatorrent.stram.plan.logical.LogicalPlan;
 import com.datatorrent.stram.plan.logical.requests.*;
 import com.datatorrent.stram.security.StramUserLogin;
 import com.datatorrent.stram.util.JSONSerializationProvider;
-import com.datatorrent.stram.util.ObjectMapperFactory;
 import com.datatorrent.stram.util.VersionInfo;
 import com.datatorrent.stram.util.WebServicesClient;
 import com.datatorrent.stram.webapp.OperatorDiscoverer;
@@ -3002,26 +3001,22 @@ public class DTCli
       String[] jarFiles = files.split(",");
       File tmpDir = copyToLocal(jarFiles);
       try {
-        ObjectMapper defaultValueMapper = ObjectMapperFactory.getOperatorValueSerializer();
-        
         OperatorDiscoverer operatorDiscoverer = new OperatorDiscoverer(jarFiles);
         String searchTerm = commandLineInfo.args.length > 1 ? commandLineInfo.args[1] : null;
-        Set<Class<? extends Operator>> operatorClasses = operatorDiscoverer.getOperatorClasses(parentName, searchTerm);
+        Set<String> operatorClasses = operatorDiscoverer.getOperatorClasses(parentName, searchTerm);
         JSONObject json = new JSONObject();
         JSONArray arr = new JSONArray();
         JSONObject portClassHier = new JSONObject();
+        JSONObject portTypesWithSchemaClasses = new JSONObject();
 
         JSONObject failed = new JSONObject();
-        JSONObject portTypesWithSchemaClasses = new JSONObject();
 
-        for (Class<? extends Operator> clazz : operatorClasses) {
+        for (final String clazz : operatorClasses) {
           try {
             JSONObject oper = operatorDiscoverer.describeOperator(clazz);
 
             // add default value
-            Operator operIns = clazz.newInstance();
-            String s = defaultValueMapper.writeValueAsString(operIns);
-            oper.put("defaultValue", new JSONObject(s).get(clazz.getName()));
+            operatorDiscoverer.addDefaultValue(clazz, oper);
             
             // add class hierarchy info to portClassHier and fetch port types with schema classes
             operatorDiscoverer.buildAdditionalPortInfo(oper, portClassHier, portTypesWithSchemaClasses);
@@ -3036,7 +3031,7 @@ public class DTCli
             arr.put(oper);
           } catch (Exception | NoClassDefFoundError ex) {
             // ignore this class
-            final String cls = clazz.getName();
+            final String cls = clazz;
             failed.put(cls, ex.toString());
           }
         }
@@ -3053,7 +3048,6 @@ public class DTCli
         FileUtils.deleteDirectory(tmpDir);
       }
     }
-
   }
 
   private class GetJarOperatorPropertiesCommand implements Command
@@ -3070,7 +3064,7 @@ public class DTCli
       try {
         OperatorDiscoverer operatorDiscoverer = new OperatorDiscoverer(jarFiles);
         Class<? extends Operator> operatorClass = operatorDiscoverer.getOperatorClass(args[2]);
-        printJson(operatorDiscoverer.describeOperator(operatorClass));
+        printJson(operatorDiscoverer.describeOperator(operatorClass.getName()));
       } finally {
         FileUtils.deleteDirectory(tmpDir);
       }

http://git-wip-us.apache.org/repos/asf/incubator-apex-core/blob/ba46e71f/engine/src/main/java/com/datatorrent/stram/webapp/OperatorDiscoverer.java
----------------------------------------------------------------------
diff --git a/engine/src/main/java/com/datatorrent/stram/webapp/OperatorDiscoverer.java b/engine/src/main/java/com/datatorrent/stram/webapp/OperatorDiscoverer.java
index 004c100..0867b03 100644
--- a/engine/src/main/java/com/datatorrent/stram/webapp/OperatorDiscoverer.java
+++ b/engine/src/main/java/com/datatorrent/stram/webapp/OperatorDiscoverer.java
@@ -15,10 +15,11 @@
  */
 package com.datatorrent.stram.webapp;
 
-import com.datatorrent.api.InputOperator;
 import com.datatorrent.api.Operator;
 import com.datatorrent.netlet.util.DTThrowable;
+import com.datatorrent.stram.util.ObjectMapperFactory;
 import com.datatorrent.stram.webapp.TypeDiscoverer.UI_TYPE;
+import com.datatorrent.stram.webapp.TypeGraph.TypeGraphVertex;
 import com.datatorrent.stram.webapp.asm.CompactAnnotationNode;
 import com.datatorrent.stram.webapp.asm.CompactFieldNode;
 import com.google.common.base.Predicate;
@@ -43,8 +44,11 @@ import java.util.regex.Pattern;
 
 import javax.xml.parsers.*;
 
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.ClassUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.text.WordUtils;
+import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jettison.json.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -62,17 +66,7 @@ import org.xml.sax.helpers.DefaultHandler;
 public class OperatorDiscoverer
 {
   public static final String GENERATED_CLASSES_JAR = "_generated-classes.jar";
-
-  private static class ClassComparator implements Comparator<Class<?>> {
-
-    @Override
-    public int compare(Class<?> a, Class<?> b)
-    {
-      return a.getName().compareTo(b.getName());
-    }
-
-  }
-  private final Set<Class<? extends Operator>> operatorClasses = new TreeSet<Class<? extends Operator>>(new ClassComparator());
+  private Set<String> operatorClassNames;
   private static final Logger LOG = LoggerFactory.getLogger(OperatorDiscoverer.class);
   private final List<String> pathsToScan = new ArrayList<String>();
   private final ClassLoader classLoader;
@@ -261,26 +255,21 @@ public class OperatorDiscoverer
     classLoader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
   }
 
-
-  @SuppressWarnings({ "unchecked" })
   private void loadOperatorClass()
   {
     buildTypeGraph();
-    String operatorRoot = Operator.class.getName();
-    Set<String> allOperatorClasses = typeGraph.getDescendants(operatorRoot);
-//    ClassLoader cLoader = new URLClassLoader();
-    for (String opClassName : allOperatorClasses) {
-      try {
-        Class<?> clazz = classLoader.loadClass(opClassName);
-//        typeGraph.get(opClassName).loadedClass = clazz;
-        if (isInstantiableOperatorClass(clazz)) {
-          LOG.debug("Adding class {} as an operator", clazz.getName());
-          operatorClasses.add((Class<? extends Operator>)clazz);
-        }
-      }
-      catch (Throwable ex) {
-        LOG.warn("Class cannot be loaded: {} (error was {})", opClassName, ex.getMessage());
-      }
+    operatorClassNames =  typeGraph.getAllDTInstantiableOperators();
+  }
+
+  @SuppressWarnings("unchecked")
+  public void addDefaultValue(String className, JSONObject oper) throws Exception
+  {
+    ObjectMapper defaultValueMapper = ObjectMapperFactory.getOperatorValueSerializer();
+    Class<? extends Operator> clazz = (Class<? extends Operator>) classLoader.loadClass(className);
+    if (clazz != null) {
+      Operator operIns = clazz.newInstance();
+      String s = defaultValueMapper.writeValueAsString(operIns);
+      oper.put("defaultValue", new JSONObject(s).get(className));
     }
   }
 
@@ -346,70 +335,51 @@ public class OperatorDiscoverer
     saxParserFactory.newSAXParser().parse(is, new JavadocSAXHandler());
   }
 
-  public static boolean isInstantiableOperatorClass(Class<?> clazz)
-  {
-    int modifiers = clazz.getModifiers();
-    if (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers) || !Operator.class.isAssignableFrom(clazz)){
-      return false;
-    }
-    // return true if it is an InputOperator or if it is an Operator with more than one InputPort
-    //TODO Use ASM later
-    return InputOperator.class.isAssignableFrom(clazz) || Iterables.any(Arrays.asList(clazz.getFields()), new Predicate<Field>() {
-      @Override
-      public boolean apply(Field f)
-      {
-        return Operator.InputPort.class.isAssignableFrom(f.getType());
-      }
-    });
-  }
-
-  public Set<Class<? extends Operator>> getOperatorClasses(String parent, String searchTerm) throws ClassNotFoundException
+  public Set<String> getOperatorClasses(String parent, String searchTerm) throws ClassNotFoundException
   {
-    if (operatorClasses.isEmpty()) {
+    if (CollectionUtils.isEmpty(operatorClassNames)) {
       loadOperatorClass();
     }
-    Class<?> parentClass;
     if (parent == null) {
-      parentClass = Operator.class;
-    }
-    else {
-      parentClass = classLoader.loadClass(parent);
-      if (!Operator.class.isAssignableFrom(parentClass)) {
+      parent = Operator.class.getName();
+    } else {
+      if (!typeGraph.isAncestor(Operator.class.getName(), parent)) {
         throw new IllegalArgumentException("Argument must be a subclass of Operator class");
       }
     }
-    Set<Class<? extends Operator>> filteredClass = Sets.filter(operatorClasses, new Predicate<Class<? extends Operator>>() {
 
+    Set<String> filteredClass = Sets.filter(operatorClassNames, new Predicate<String>()
+    {
       @Override
-      public boolean apply(Class<? extends Operator> c)
+      public boolean apply(String className)
       {
-        OperatorClassInfo oci = classInfo.get(c.getName());
+        OperatorClassInfo oci = classInfo.get(className);
         return oci == null || !oci.tags.containsKey("@omitFromUI");
       }
     });
-    if (searchTerm == null && parentClass == Operator.class) {
-      return Collections.unmodifiableSet(filteredClass);
+
+    if (searchTerm == null && parent == Operator.class.getName()) {
+      return filteredClass;
     }
+
     if (searchTerm != null) {
       searchTerm = searchTerm.toLowerCase();
     }
-    Set<Class<? extends Operator>> result = new HashSet<Class<? extends Operator>>();
-    for (Class<? extends Operator> clazz : filteredClass) {
-      if (parentClass.isAssignableFrom(clazz)) {
+
+    Set<String> result = new HashSet<String>();
+    for (String clazz : filteredClass) {
+      if (parent == Operator.class.getName() || typeGraph.isAncestor(parent, clazz)) {
         if (searchTerm == null) {
           result.add(clazz);
-        }
-        else {
-          if (clazz.getName().toLowerCase().contains(searchTerm)) {
+        } else {
+          if (clazz.toLowerCase().contains(searchTerm)) {
             result.add(clazz);
-          }
-          else {
-            OperatorClassInfo oci = classInfo.get(clazz.getName());
+          } else {
+            OperatorClassInfo oci = classInfo.get(clazz);
             if (oci != null) {
               if (oci.comment != null && oci.comment.toLowerCase().contains(searchTerm)) {
                 result.add(clazz);
-              }
-              else {
+              } else {
                 for (Map.Entry<String, String> entry : oci.tags.entrySet()) {
                   if (entry.getValue().toLowerCase().contains(searchTerm)) {
                     result.add(clazz);
@@ -428,7 +398,7 @@ public class OperatorDiscoverer
   @SuppressWarnings("unchecked")
   public Class<? extends Operator> getOperatorClass(String className) throws ClassNotFoundException
   {
-    if (operatorClasses.isEmpty()) {
+    if (CollectionUtils.isEmpty(operatorClassNames)) {
       loadOperatorClass();
     }
 
@@ -440,23 +410,24 @@ public class OperatorDiscoverer
     return (Class<? extends Operator>)clazz;
   }
 
-  public JSONObject describeOperator(Class<? extends Operator> clazz) throws Exception
+  public JSONObject describeOperator(String clazz) throws Exception
   {
-    if (OperatorDiscoverer.isInstantiableOperatorClass(clazz)) {
+    TypeGraphVertex tgv = typeGraph.getTypeGraphVertex(clazz);
+    if (tgv.isInstantiable()) {
       JSONObject response = new JSONObject();
       JSONArray inputPorts = new JSONArray();
       JSONArray outputPorts = new JSONArray();
       // Get properties from ASM
 
-      JSONObject operatorDescriptor =  describeClassByASM(clazz.getName());
+      JSONObject operatorDescriptor =  describeClassByASM(clazz);
       JSONArray properties = operatorDescriptor.getJSONArray("properties");
 
       properties = enrichProperties(clazz, properties);
 
       JSONArray portTypeInfo = operatorDescriptor.getJSONArray("portTypeInfo");
 
-      List<CompactFieldNode> inputPortfields = typeGraph.getAllInputPorts(clazz.getName());
-      List<CompactFieldNode> outputPortfields = typeGraph.getAllOutputPorts(clazz.getName());
+      List<CompactFieldNode> inputPortfields = typeGraph.getAllInputPorts(clazz);
+      List<CompactFieldNode> outputPortfields = typeGraph.getAllOutputPorts(clazz);
 
 
       try {
@@ -486,13 +457,13 @@ public class OperatorDiscoverer
           outputPorts.put(outputPort);
         }
 
-        response.put("name", clazz.getName());
+        response.put("name", clazz);
         response.put("properties", properties);
         response.put(PORT_TYPE_INFO_KEY, portTypeInfo);
         response.put("inputPorts", inputPorts);
         response.put("outputPorts", outputPorts);
 
-        OperatorClassInfo oci = classInfo.get(clazz.getName());
+        OperatorClassInfo oci = classInfo.get(clazz);
 
         if (oci != null) {
           if (oci.comment != null) {
@@ -515,7 +486,7 @@ public class OperatorDiscoverer
           response.put("category", oci.tags.get("@category"));
           String displayName = oci.tags.get("@displayName");
           if (displayName == null) {
-            displayName = decamelizeClassName(clazz.getSimpleName());
+            displayName = decamelizeClassName(ClassUtils.getShortClassName(clazz));
           }
           response.put("displayName", displayName);
           String tags = oci.tags.get("@tags");
@@ -530,9 +501,9 @@ public class OperatorDiscoverer
           if (doclink != null) {
             response.put("doclink", doclink + "?" + getDocName(clazz));
           }
-          else if (clazz.getName().startsWith("com.datatorrent.lib.") ||
-                  clazz.getName().startsWith("com.datatorrent.contrib.")) {
-            response.put("doclink", DT_OPERATOR_DOCLINK_PREFIX + "?" + getDocName(clazz));
+          else if (clazz.startsWith("com.datatorrent.lib.") ||
+                  clazz.startsWith("com.datatorrent.contrib.")) {
+            response.put("doclink", DT_OPERATOR_DOCLINK_PREFIX  + "?" + getDocName(clazz));
           }
         }
       }
@@ -546,29 +517,18 @@ public class OperatorDiscoverer
     }
   }
 
-  private JSONObject setFieldAttributes(Class<? extends Operator> clazz,
-      CompactFieldNode field) throws JSONException {
+  private JSONObject setFieldAttributes(String clazz, CompactFieldNode field) throws JSONException
+  {
     JSONObject port = new JSONObject();
     port.put("name", field.getName());
 
-    for (Class<?> c = clazz; c != null; c = c.getSuperclass()) {
-      OperatorClassInfo oci = classInfo.get(c.getName());
-      if (oci != null) {
-        String fieldDesc = oci.fields.get(field.getName());
-        if (fieldDesc != null) {
-          port.put("description", fieldDesc);
-          break;
-        }
-      }
-    }
+    TypeGraphVertex tgv = typeGraph.getTypeGraphVertex(clazz);
+    putFieldDescription(field, port, tgv);
 
     List<CompactAnnotationNode> annotations = field.getVisibleAnnotations();
     CompactAnnotationNode firstAnnotation;
-    if (annotations != null
-        && !annotations.isEmpty()
-        && (firstAnnotation = field
-        .getVisibleAnnotations().get(0)) != null) {
-      for(Map.Entry<String, Object> entry :firstAnnotation.getAnnotations().entrySet() ) {
+    if (annotations != null && !annotations.isEmpty() && (firstAnnotation = field.getVisibleAnnotations().get(0)) != null) {
+      for (Map.Entry<String, Object> entry : firstAnnotation.getAnnotations().entrySet()) {
         port.put(entry.getKey(), entry.getValue());
       }
     }
@@ -576,7 +536,23 @@ public class OperatorDiscoverer
     return port;
   }
 
-  private JSONArray enrichProperties(Class<?> operatorClass, JSONArray properties) throws JSONException
+  private void putFieldDescription(CompactFieldNode field, JSONObject port, TypeGraphVertex tgv) throws JSONException
+  {
+    OperatorClassInfo oci = classInfo.get(tgv.typeName);
+    if (oci != null) {
+      String fieldDesc = oci.fields.get(field.getName());
+      if (fieldDesc != null) {
+        port.put("description", fieldDesc);
+        return;
+      }
+    }
+
+    for (TypeGraphVertex ancestor : tgv.getAncestors()) {
+      putFieldDescription(field, port, ancestor);
+    }
+  }
+
+  private JSONArray enrichProperties(String operatorClass, JSONArray properties) throws JSONException
   {
     JSONArray result = new JSONArray();
     for (int i = 0; i < properties.length(); i++) {
@@ -602,16 +578,26 @@ public class OperatorDiscoverer
     return result;
   }
 
-  private OperatorClassInfo getOperatorClassWithGetterSetter(Class<?> operatorClass, String setterName, String getterName) {
-    if(operatorClass != null && !Operator.class.isAssignableFrom(operatorClass)){
-      return null;
-    }
-    OperatorClassInfo oci = classInfo.get(operatorClass.getName());
-    if(oci != null && (oci.getMethods.containsKey(getterName) || oci.setMethods.containsKey(setterName))){
+  private OperatorClassInfo getOperatorClassWithGetterSetter(String operatorClass, String setterName, String getterName)
+  {
+    TypeGraphVertex tgv = typeGraph.getTypeGraphVertex(operatorClass);
+    return getOperatorClassWithGetterSetter(tgv, setterName, getterName);
+  }
+
+  private OperatorClassInfo getOperatorClassWithGetterSetter(TypeGraphVertex tgv, String setterName, String getterName)
+  {
+    OperatorClassInfo oci = classInfo.get(tgv.typeName);
+    if (oci != null && (oci.getMethods.containsKey(getterName) || oci.setMethods.containsKey(setterName))) {
       return oci;
     } else {
-      return getOperatorClassWithGetterSetter(operatorClass.getSuperclass(), setterName, getterName);
+      if (tgv.getAncestors() != null) {
+        for (TypeGraphVertex ancestor : tgv.getAncestors()) {
+          return getOperatorClassWithGetterSetter(ancestor, setterName, getterName);
+        }
+      }
     }
+
+    return null;
   }
 
   private void addTagsToProperties(MethodInfo mi, JSONObject propJ) throws JSONException
@@ -675,9 +661,9 @@ public class OperatorDiscoverer
   }
 
 
-  private static String getDocName(Class<?> clazz)
+  private static String getDocName(String clazz)
   {
-    return clazz.getName().replace('.', '/').replace('$', '.') + ".html";
+    return clazz.replace('.', '/').replace('$', '.') + ".html";
   }
 
   private JSONArray getClassProperties(Class<?> clazz, int level) throws IntrospectionException

http://git-wip-us.apache.org/repos/asf/incubator-apex-core/blob/ba46e71f/engine/src/main/java/com/datatorrent/stram/webapp/StramWebServices.java
----------------------------------------------------------------------
diff --git a/engine/src/main/java/com/datatorrent/stram/webapp/StramWebServices.java b/engine/src/main/java/com/datatorrent/stram/webapp/StramWebServices.java
index 010a976..97edf39 100644
--- a/engine/src/main/java/com/datatorrent/stram/webapp/StramWebServices.java
+++ b/engine/src/main/java/com/datatorrent/stram/webapp/StramWebServices.java
@@ -288,11 +288,11 @@ public class StramWebServices
     }
 
     try {
-      Set<Class<? extends Operator>> operatorClasses = operatorDiscoverer.getOperatorClasses(parent, searchTerm);
+      Set<String> operatorClasses = operatorDiscoverer.getOperatorClasses(parent, searchTerm);
 
-      for (Class<?> clazz : operatorClasses) {
+      for (String clazz : operatorClasses) {
         JSONObject j = new JSONObject();
-        j.put("name", clazz.getName());
+        j.put("name", clazz);
         classNames.put(j);
       }
 
@@ -318,7 +318,7 @@ public class StramWebServices
     try {
       Class<?> clazz = Class.forName(className);
       if (Operator.class.isAssignableFrom(clazz)) {
-        return operatorDiscoverer.describeOperator((Class<? extends Operator>)clazz);
+        return operatorDiscoverer.describeOperator(className);
       }
       else {
         throw new NotFoundException();

http://git-wip-us.apache.org/repos/asf/incubator-apex-core/blob/ba46e71f/engine/src/main/java/com/datatorrent/stram/webapp/TypeGraph.java
----------------------------------------------------------------------
diff --git a/engine/src/main/java/com/datatorrent/stram/webapp/TypeGraph.java b/engine/src/main/java/com/datatorrent/stram/webapp/TypeGraph.java
index 61dc99d..d0b34c2 100644
--- a/engine/src/main/java/com/datatorrent/stram/webapp/TypeGraph.java
+++ b/engine/src/main/java/com/datatorrent/stram/webapp/TypeGraph.java
@@ -37,6 +37,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.datatorrent.api.Component;
+import com.datatorrent.api.InputOperator;
 import com.datatorrent.api.Operator;
 import com.datatorrent.netlet.util.DTThrowable;
 import com.datatorrent.stram.webapp.asm.ClassNodeType;
@@ -91,6 +92,22 @@ public class TypeGraph
     JACKSON_INSTANTIABLE_CLASSES = b.build();
   }
 
+  public boolean isAncestor(String parentClassName, String subClassName)
+  {
+    TypeGraphVertex parentVertex = typeGraph.get(parentClassName);
+    TypeGraphVertex classVertex = typeGraph.get(subClassName);
+
+    if(parentVertex == null || classVertex == null)
+      return false;
+
+    return TypeGraph.isAncestor(parentVertex, classVertex);
+  }
+
+  public TypeGraphVertex getTypeGraphVertex(String className)
+  {
+    return typeGraph.get(className);
+  }
+
   private static boolean isAncestor(TypeGraphVertex typeTgv, TypeGraphVertex tgv)
   {
     if (tgv == typeTgv) {
@@ -368,6 +385,22 @@ public class TypeGraph
     return typeGraph.size();
   }
 
+  public Set<String> getAllDTInstantiableOperators()
+  {
+    TypeGraphVertex tgv = typeGraph.get(Operator.class.getName());
+    if (tgv == null) {
+      return null;
+    }
+    Set<String> result = new TreeSet<String>();
+    for (TypeGraphVertex node : tgv.allInstantiableDescendants) {
+      if ((isAncestor(InputOperator.class.getName(), node.typeName) || !getAllInputPorts(node).isEmpty())) {
+        result.add(node.typeName);
+      }
+    }
+
+    return result;
+  }
+
   public Set<String> getDescendants(String fullClassName)
   {
     Set<String> result = new HashSet<String>();
@@ -456,6 +489,10 @@ public class TypeGraph
       this.classNode = classNode;
     }
 
+    public Set<TypeGraphVertex> getAncestors()
+    {
+      return ancestors;
+    }
     public int numberOfInstantiableDescendants()
     {
       return allInstantiableDescendants.size() + (isInstantiable() ? 1 : 0);
@@ -467,7 +504,7 @@ public class TypeGraph
       this.jarName = jarName;
     }
 
-    private boolean isInstantiable()
+    public boolean isInstantiable()
     {
       return JACKSON_INSTANTIABLE_CLASSES.contains(this.typeName) || (isPublicConcrete() && classNode.getDefaultConstructor() != null);
     }
@@ -682,9 +719,17 @@ public class TypeGraph
     return null;
   }
 
-  public List<CompactFieldNode> getAllInputPorts(String clazzName) {
+  public List<CompactFieldNode> getAllInputPorts(String clazzName)
+  {
     TypeGraphVertex tgv = typeGraph.get(clazzName);
+    return getAllInputPorts(tgv);
+  }
+
+  public List<CompactFieldNode> getAllInputPorts(TypeGraphVertex tgv)
+  {
     List<CompactFieldNode> ports = new ArrayList<CompactFieldNode>();
+    if (tgv == null)
+      return ports;
     TypeGraphVertex portVertex = typeGraph.get(Operator.InputPort.class
         .getName());
     getAllPortsWithAncestor(portVertex, tgv, ports);
@@ -694,26 +739,28 @@ public class TypeGraph
         return a.getName().compareTo(b.getName());
       }
     });
+
     return ports;
   }
 
-  public List<CompactFieldNode> getAllOutputPorts(String clazzName) {
+  public List<CompactFieldNode> getAllOutputPorts(String clazzName)
+  {
     TypeGraphVertex tgv = typeGraph.get(clazzName);
     List<CompactFieldNode> ports = new ArrayList<CompactFieldNode>();
-    TypeGraphVertex portVertex = typeGraph.get(Operator.OutputPort.class
-        .getName());
+    TypeGraphVertex portVertex = typeGraph.get(Operator.OutputPort.class.getName());
     getAllPortsWithAncestor(portVertex, tgv, ports);
-    Collections.sort(ports, new Comparator<CompactFieldNode>() {
+    Collections.sort(ports, new Comparator<CompactFieldNode>()
+    {
       @Override
-      public int compare(CompactFieldNode a, CompactFieldNode b) {
+      public int compare(CompactFieldNode a, CompactFieldNode b)
+      {
         return a.getName().compareTo(b.getName());
       }
     });
     return ports;
   }
-  
-  private void getAllPortsWithAncestor(TypeGraphVertex portVertex,
-      TypeGraphVertex tgv, List<CompactFieldNode> ports)
+
+  private void getAllPortsWithAncestor(TypeGraphVertex portVertex, TypeGraphVertex tgv, List<CompactFieldNode> ports)
   {
     List<CompactFieldNode> fields = tgv.getClassNode().getPorts();
     if (fields != null) {
@@ -730,21 +777,22 @@ public class TypeGraph
     }
   }
 
-  private void addClassPropertiesAndPorts(String clazzName, JSONObject desc) throws JSONException {
+  private void addClassPropertiesAndPorts(String clazzName, JSONObject desc) throws JSONException
+  {
     TypeGraphVertex tgv = typeGraph.get(clazzName);
     if (tgv == null) {
       return;
     }
 
     Map<String, JSONObject> results = new TreeMap<String, JSONObject>();
-    List<CompactMethodNode> getters =  new LinkedList<CompactMethodNode>();
+    List<CompactMethodNode> getters = new LinkedList<CompactMethodNode>();
     List<CompactMethodNode> setters = new LinkedList<CompactMethodNode>();
     Map<Type, Type> typeReplacement = new HashMap<Type, Type>();
-    List<CompactFieldNode> ports =  new LinkedList<CompactFieldNode>();
-    
+    List<CompactFieldNode> ports = new LinkedList<CompactFieldNode>();
+
     getPublicSetterGetterAndPorts(tgv, setters, getters, typeReplacement, ports);
     desc.put("portTypeInfo", getPortTypeInfo(clazzName, typeReplacement, ports));
-    
+
     for (CompactMethodNode setter : setters) {
       String prop = WordUtils.uncapitalize(setter.getName().substring(3));
       JSONObject propJ = results.get(prop);
@@ -756,13 +804,12 @@ public class TypeGraph
       propJ.put("canSet", true);
       propJ.put("canGet", false);
 
-
       MethodSignatureVisitor msv = null;
       msv = setter.getMethodSignatureNode();
-      if(msv==null){
+      if (msv == null) {
         continue;
       }
-      
+
       List<Type> param = msv.getParameters();
       if (CollectionUtils.isEmpty(param)) {
         propJ.put("type", "UNKNOWN");
@@ -788,10 +835,9 @@ public class TypeGraph
 
         MethodSignatureVisitor msv = null;
         msv = getter.getMethodSignatureNode();
-        if(msv==null){
+        if (msv == null) {
           continue;
         }
-        
 
         Type rt = msv.getReturnType();
         if (rt == null) {

http://git-wip-us.apache.org/repos/asf/incubator-apex-core/blob/ba46e71f/engine/src/test/java/com/datatorrent/stram/webapp/OperatorDiscoveryTest.java
----------------------------------------------------------------------
diff --git a/engine/src/test/java/com/datatorrent/stram/webapp/OperatorDiscoveryTest.java b/engine/src/test/java/com/datatorrent/stram/webapp/OperatorDiscoveryTest.java
index 8baa08a..0f2fc13 100644
--- a/engine/src/test/java/com/datatorrent/stram/webapp/OperatorDiscoveryTest.java
+++ b/engine/src/test/java/com/datatorrent/stram/webapp/OperatorDiscoveryTest.java
@@ -190,7 +190,8 @@ public class OperatorDiscoveryTest
     String[] classFilePath = getClassFileInClasspath();
     OperatorDiscoverer operatorDiscoverer = new OperatorDiscoverer(classFilePath);
     operatorDiscoverer.buildTypeGraph();
-    JSONObject oper = operatorDiscoverer.describeOperator(SubSubClassGeneric.class);
+    JSONObject oper = operatorDiscoverer.describeOperator(SubSubClassGeneric.class.getName());
+
     String debug = "\n(ASM)type info for " + TestOperator.class + ":\n" + oper.toString(2) + "\n";
 
     JSONArray props = oper.getJSONArray("properties");
@@ -277,8 +278,6 @@ public class OperatorDiscoveryTest
     od.buildTypeGraph();
 
     Assert.assertNotNull(od.getOperatorClass(BaseOperator.class.getName()));
-    Assert.assertFalse("Base Operator is not instantiable because it is not an InputOperator and it has no input port ",
-            OperatorDiscoverer.isInstantiableOperatorClass(BaseOperator.class));
 
     JSONObject asmDesc = od.describeClassByASM(TestOperator.class.getName());
     String debug = "\n(ASM)type info for " + TestOperator.class + ":\n" + asmDesc.toString(2) + "\n";
@@ -1057,7 +1056,7 @@ public class OperatorDiscoveryTest
     String[] classFilePath = getClassFileInClasspath();
     OperatorDiscoverer od = new OperatorDiscoverer(classFilePath);
     od.buildTypeGraph();
-    JSONObject operatorJson = od.describeOperator(SchemaRequiredOperator.class);
+    JSONObject operatorJson = od.describeOperator(SchemaRequiredOperator.class.getName());
     JSONArray portsJson = operatorJson.getJSONArray("outputPorts");
 
     Assert.assertEquals("no. of ports", 3, portsJson.length());
@@ -1081,7 +1080,7 @@ public class OperatorDiscoveryTest
     String[] classFilePath = getClassFileInClasspath();
     OperatorDiscoverer operatorDiscoverer = new OperatorDiscoverer(classFilePath);
     operatorDiscoverer.buildTypeGraph();
-    JSONObject operator = operatorDiscoverer.describeOperator(SubSubClassGeneric.class);
+    JSONObject operator = operatorDiscoverer.describeOperator(SubSubClassGeneric.class.getName());
 
     JSONObject portClassHierarchy = new JSONObject();
     JSONObject portsWithSchemaClasses = new JSONObject();