gt:                             if (path == null) {
context: package org.exoplatform.addons.restapidoc;
  
  import com.fasterxml.jackson.databind.JavaType;
  import com.fasterxml.jackson.databind.type.TypeFactory;
  import com.google.common.collect.Collections2;
  import io.swagger.annotations.*;
  import io.swagger.annotations.Info;
  import io.swagger.converter.ModelConverters;
  import io.swagger.jaxrs.PATCH;
  import io.swagger.jaxrs.ParameterProcessor;
  import io.swagger.jaxrs.Reader;
  import io.swagger.jaxrs.config.ReaderConfig;
  import io.swagger.jaxrs.config.ReaderListener;
  import io.swagger.jaxrs.ext.SwaggerExtension;
  import io.swagger.jaxrs.ext.SwaggerExtensions;
  import io.swagger.jaxrs.utils.ReflectionUtils;
  import io.swagger.models.*;
  import io.swagger.models.Contact;
  import io.swagger.models.ExternalDocs;
  import io.swagger.models.License;
  import io.swagger.models.Path;
  import io.swagger.models.Tag;
  import io.swagger.models.parameters.*;
  import io.swagger.models.properties.ArrayProperty;
  import io.swagger.models.properties.MapProperty;
  import io.swagger.models.properties.Property;
  import io.swagger.models.properties.RefProperty;
  import org.apache.commons.lang3.StringUtils;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import javax.ws.rs.*;
  import java.lang.annotation.Annotation;
  import java.lang.reflect.*;
  import java.util.*;
  
  /**
   * Created by tgigant on 7/23/15.
   */
  public class CustomReader extends Reader {
      private static final Logger LOGGER = LoggerFactory.getLogger(Reader.class);
      private static final String PATH_DELIMITER = "/";
      private static final String SUCCESSFUL_OPERATION = "successful operation";
      private static final Set<Class<? extends Annotation>> FIELD_ANNOTATIONS;
      //private Swagger swagger = new Swagger();
  //    String sep = " ###################### ";
  
      public CustomReader(Swagger swagger, ReaderConfig config) {
          super(swagger, config);
      }
  
      public CustomReader(Swagger swagger) {
          super(swagger);
      }
  
  
      /**
       * Scans a set of classes for both ReaderListeners and Swagger annotations. All found listeners will
       * be instantiated before any of the classes are scanned for Swagger annotations - so they can be invoked
       * accordingly.
       *
       * @param classes a set of classes to scan
       * @return the generated Swagger definition
       */
      @Override
      public Swagger read(Set<Class<?>> classes) {
  
          Map<Class<?>, ReaderListener> listeners = new HashMap<Class<?>, ReaderListener>();
  
          for (Class<?> cls : classes) {
              if (ReaderListener.class.isAssignableFrom(cls) && !listeners.containsKey(cls)) {
                  try {
                      listeners.put(cls, (ReaderListener) cls.newInstance());
                  } catch (Exception e) {
                      LOGGER.error("Failed to create ReaderListener", e);
                  }
              }
          }
  
          for (ReaderListener listener : listeners.values()) {
              try {
                  listener.beforeScan(this, getSwagger());
              } catch (Exception e) {
                  LOGGER.error("Unexpected error invoking beforeScan listener [" + listener.getClass().getName() + "]", e);
              }
          }
  
  //        System.out.println(sep + "CustomReader : swagger initialization" + sep);
  //        System.out.println(sep + "before initialization");
  //        System.out.println("Swagger : " + getSwagger().getTags());
  
          for (Class<?> cls : classes) {
              read(cls);
          }
  //        System.out.println(sep + "after initialization");
  //        System.out.println("Swagger : " + getSwagger().getTags());
  
          for (ReaderListener listener : listeners.values()) {
              try {
                  listener.afterScan(this, getSwagger());
              } catch (Exception e) {
                  LOGGER.error("Unexpected error invoking afterScan listener [" + listener.getClass().getName() + "]", e);
              }
          }
  
          return getSwagger();
      }
  
      /**
       * Scans a single class for Swagger annotations - does not invoke ReaderListeners
       */
      @Override
      public Swagger read(Class<?> cls) {
          return read(cls, "", null, false, new String[0], new String[0], new HashMap<String, Tag>(), new ArrayList<Parameter>());
      }
  
  
      @Override
      protected Swagger read(Class<?> cls, String parentPath, String parentMethod, boolean readHidden, String[] parentConsumes, String[] parentProduces, Map<String, Tag> parentTags, List<Parameter> parentParameters) {
          SwaggerDefinition swaggerDefinition = cls.getAnnotation(SwaggerDefinition.class);
          if (swaggerDefinition != null) {
              readSwaggerConfig(cls, swaggerDefinition);
          }
  
  //        System.out.println(sep + "Trying to get annotations from " + cls.getCanonicalName() + sep);
          Api api = (Api) cls.getAnnotation(Api.class);
  //        System.out.println(sep + "Api null ? : " + (api == null));
  
  
  
          Map<String, Tag> tags = new HashMap<String, Tag>();
          List<SecurityRequirement> securities = new ArrayList<SecurityRequirement>();
  
          String[] consumes = new String[0];
          String[] produces = new String[0];
          final Set<Scheme> globalSchemes = EnumSet.noneOf(Scheme.class);
  
          // only read if allowing hidden apis OR api is not marked as hidden
          final boolean readable = (api != null && readHidden) || (api != null && !api.hidden());
  
          //if (readable || cls.getCanonicalName().toString().equals("org.exoplatform.tgigant.TestJar")) {
          if (readable) {
  
  //            System.out.println(sep + "The api is readable" + sep);
  
              // the value will be used as a tag for 2.0 UNLESS a Tags annotation is present
              Set<String> tagStrings = extractTags(api);
              for (String tagString : tagStrings) {
                  Tag tag = new Tag().name(tagString);
                  tags.put(tagString, tag);
              }
              if (parentTags != null) {
                  tags.putAll(parentTags);
              }
              for (String tagName : tags.keySet()) {
                  getSwagger().tag(tags.get(tagName));
              }
  
              if (!api.produces().isEmpty()) {
                  produces = new String[]{api.produces()};
              } else if (cls.getAnnotation(Produces.class) != null) {
                  produces = ((Produces) cls.getAnnotation(Produces.class)).value();
              }
              if (!api.consumes().isEmpty()) {
                  consumes = new String[]{api.consumes()};
              } else if (cls.getAnnotation(Consumes.class) != null) {
                  consumes = ((Consumes) cls.getAnnotation(Consumes.class)).value();
              }
              globalSchemes.addAll(parseSchemes(api.protocols()));
              Authorization[] authorizations = api.authorizations();
  
              for (Authorization auth : authorizations) {
                  if (auth.value() != null && !"".equals(auth.value())) {
                      SecurityRequirement security = new SecurityRequirement();
                      security.setName(auth.value());
                      AuthorizationScope[] scopes = auth.scopes();
                      for (AuthorizationScope scope : scopes) {
                          if (scope.scope() != null && !"".equals(scope.scope())) {
                              security.addScope(scope.scope());
                          }
                      }
                      securities.add(security);
                  }
              }
          }
  
  //        System.out.println(sep+"Mid reading class"+sep);
  
          // allow reading the JAX-RS APIs without @Api annotation
          if (readable || (api == null && getConfig().isScanAllResources())) {
              // merge consumes, produces
  
              // look for method-level annotated properties
  
              // handle sub-resources by looking at return type
  
              // parse the method
              final javax.ws.rs.Path apiPath = cls.getAnnotation(javax.ws.rs.Path.class);
              Method methods[] = cls.getMethods();
              for (Method method : methods) {
                  if (ReflectionUtils.isOverriddenMethod(method, cls)) {
                      continue;
                  }
                  javax.ws.rs.Path methodPath = getAnnotation(method, javax.ws.rs.Path.class);
  
                  String operationPath = getPath(apiPath, methodPath, parentPath);
                  if (operationPath != null) {
                      String[] pps = operationPath.split("/");
                      String[] pathParts = new String[pps.length];
                      Map<String, String> regexMap = new HashMap<String, String>();
  
                      for (int i = 0; i < pps.length; i++) {
                          String p = pps[i];
                          if (p.startsWith("{")) {
                              int pos = p.indexOf(":");
                              if (pos > 0) {
                                  String left = p.substring(1, pos);
                                  String right = p.substring(pos + 1, p.length() - 1);
                                  pathParts[i] = "{" + left + "}";
                                  regexMap.put(left, right);
                              } else {
                                  pathParts[i] = p;
                              }
                          } else {
                              pathParts[i] = p;
                          }
                      }
                      StringBuilder pathBuilder = new StringBuilder();
                      for (String p : pathParts) {
                          if (!p.isEmpty()) {
                              pathBuilder.append("/").append(p);
                          }
                      }
                      operationPath = pathBuilder.toString();
  
                      if (isIgnored(operationPath)) {
                          continue;
                      }
  
                      final ApiOperation apiOperation = getAnnotation(method, ApiOperation.class);
                      String httpMethod = extractOperationMethod(apiOperation, method, SwaggerExtensions.chain());
  
                      Operation operation = parseMethod(method, collectGlobalParameters(cls));
                      if (operation == null) {
                          continue;
                      }
                      if (parentParameters != null) {
                          for (Parameter param : parentParameters) {
                              operation.parameter(param);
                          }
                      }
                      for (Parameter param : operation.getParameters()) {
                          if (regexMap.get(param.getName()) != null) {
                              String pattern = regexMap.get(param.getName());
                              param.setPattern(pattern);
                          }
                      }
  
                      if (apiOperation != null) {
                          for (Scheme scheme : parseSchemes(apiOperation.protocols())) {
                              operation.scheme(scheme);
                          }
                      }
  
                      if (operation.getSchemes() == null || operation.getSchemes().isEmpty()) {
                          for (Scheme scheme : globalSchemes) {
                              operation.scheme(scheme);
                          }
                      }
  
                      String[] apiConsumes = consumes;
                      if (parentConsumes != null) {
                          Set<String> both = new HashSet<String>(Arrays.asList(apiConsumes));
                          both.addAll(new HashSet<String>(Arrays.asList(parentConsumes)));
                          if (operation.getConsumes() != null) {
                              both.addAll(new HashSet<String>(operation.getConsumes()));
                          }
                          apiConsumes = both.toArray(new String[both.size()]);
                      }
  
                      String[] apiProduces = produces;
                      if (parentProduces != null) {
                          Set<String> both = new HashSet<String>(Arrays.asList(apiProduces));
                          both.addAll(new HashSet<String>(Arrays.asList(parentProduces)));
                          if (operation.getProduces() != null) {
                              both.addAll(new HashSet<String>(operation.getProduces()));
                          }
                          apiProduces = both.toArray(new String[both.size()]);
                      }
                      final Class<?> subResource = getSubResource(method);
                      if (subResource != null) {
                          read(subResource, operationPath, httpMethod, true, apiConsumes, apiProduces, tags, operation.getParameters());
                      }
  
                      // can't continue without a valid http method
                      httpMethod = httpMethod == null ? parentMethod : httpMethod;
                      if (httpMethod != null) {
                          if (apiOperation != null) {
                              boolean hasExplicitTag = false;
                              for (String tag : apiOperation.tags()) {
                                  if (!"".equals(tag)) {
                                      operation.tag(tag);
                                      getSwagger().tag(new Tag().name(tag));
                                  }
                              }
  
                              if (operation != null) {
                                  addExtensionProperties(apiOperation.extensions(), operation.getVendorExtensions());
                              }
                          }
                          if (operation != null) {
                              if (operation.getConsumes() == null) {
                                  for (String mediaType : apiConsumes) {
                                      operation.consumes(mediaType);
                                  }
                              }
                              if (operation.getProduces() == null) {
                                  for (String mediaType : apiProduces) {
                                      operation.produces(mediaType);
                                  }
                              }
  
                              if (operation.getTags() == null) {
                                  for (String tagString : tags.keySet()) {
                                      operation.tag(tagString);
                                  }
                              }
                              // Only add global @Api securities if operation doesn't already have more specific securities
                              if (operation.getSecurity() == null) {
                                  for (SecurityRequirement security : securities) {
                                      operation.security(security);
                                  }
                              }
  
                              Path path = getSwagger().getPath(operationPath);
  