Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * #%L
   * FlatPack Automatic Source Tool
   * %%
   * Copyright (C) 2012 Perka 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.
  * #L%
  */
 package com.getperka.flatpack.fast;
 
 import java.io.File;
 import java.io.Writer;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 
 
Generates simple Java POJO representations of a FlatPack API.
 
 public class JavaDialect implements Dialect {
   @Flag(tag = "apiIsPublic",
       help = "If false, the generated Api class will have package visibility",
       defaultValue = "true")
   static Boolean apiIsPublic;
 
  @Flag(tag = "packageName",
      help = "The name of the package that generated sources should belong to",
      defaultValue = "com.getperka.fast")
  static String packageName;
  @Flag(tag = "stripPathSegments",
      help = "The number of path segments to strip when creating method names", defaultValue = "0")
  @Flag(
      tag = "baseTypeArray",
      help = "A file containing a JSON array of payload names for DTOs that should be generated as a base type")
  @Flag(tag = "typePrefix", help = "A prefix to apply to all generated type names",
      defaultValue = "")
  static String typePrefix = "";
  private static final Charset UTF8 = Charset.forName("UTF8");
  private static final List<Class<?>> WELL_KNOWN_TYPES = Arrays.<Class<?>> asList(
      ApiBase.classArrays.classConnectionRequestBase.classCollections.classDirtyFlag.class,
      Embedded.classFlatPack.classFlatPackCollections.classFlatPackEntity.class,
      FlatPackRequest.classFlatPackRequestBase.classFlatPackTypes.classHashSet.class,
      HttpURLConnection.classInheritPrincipal.classIOException.classJsonTypeName.class,
      PermitAll.classPersistenceAware.classPostUnpack.classRequest.classRolesAllowed.class,
      Set.classSparseCollection.classSuppressDefaultValue.classTypeReference.class,
      TypeSource.class);
  private static String upcase(String typeName) {
    return Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
  }
  private final Set<StringbaseTypes = new HashSet<String>();
  private final Logger logger = LoggerFactory.getLogger(getClass());
  
Used at the end of the code-generation process to emit referenced enum values.
  private final Set<TypeusedEnums = new LinkedHashSet<Type>();
  public void generate(ApiDescription apiFile outputDirthrows IOException {
    STGroup group = loadGroup();
    File packageDir = new File(outputDir.replace('.''/'));
    if (!packageDir.isDirectory() && !packageDir.mkdirs()) {
      .error("Could not create output directory {}"packageDir.getPath());
      return;
    }
    Map<StringEntityDescriptionallEntities = FlatPackCollections.mapForIteration();
    for (EntityDescription entity : api.getEntities()) {
      addEntity(allEntitiesentity);
    }
    // Render entities
    for (EntityDescription entity : allEntities.values()) {
      ST entityST = group.getInstanceOf("entity")
          .add("entity"entity)
          .add("packageName");
      String simpleName =  + upcase(entity.getTypeName());
      if (.contains(entity.getTypeName())) {
        simpleName += "Base";
      }
      render(entitySTpackageDirsimpleName);
    }
    // Render referenced enumerations
    for (Type enumType : ) {
      ST enumST = group.getInstanceOf("enum")
          .add("enum"enumType)
          .add("packageName");
      render(enumSTpackageDir + upcase(enumType.getName()));
    }
    String namePrefix = upcase(.substring(.lastIndexOf('.') + 1));
    // Render the Api convenience class
    ST apiST = group.getInstanceOf("api")
        .add("api"api)
        .add("packageName")
        .add("namePrefix"namePrefix)
        .add("apiIsPublic");
    render(apiSTpackageDirnamePrefix + "Api");
    // Emit a manifest of all generated types
    ST typeSourceST = group.getInstanceOf("typeSource")
        .add("allEntities"allEntities.values())
        .add("packageName")
        .add("namePrefix"namePrefix);
    render(typeSourceSTpackageDirnamePrefix + "TypeSource");
  }
  public String getDialectName() {
    return "java";
  }

  
Adds an entity and its supertypes to a map. The properties defined by the entity will be pruned so that the entity contains only its declared properties.

Parameters:
allEntities an accumulator map of entity payload names to descriptions
entity the entity to add
  protected void addEntity(Map<StringEntityDescriptionallEntitiesEntityDescription entity) {
    if (entity == null) {
      return;
    }
    String typeName = entity.getTypeName();
    if (allEntities.containsKey(typeName)) {
      // Already processed
      return;
    } else if ("baseHasUuid".equals(typeName) || "hasUuid".equals(typeName)) {
      // Ensure that the "real" implementations are used
      return;
    }
    allEntities.put(typeNameentity);
    for (Iterator<Propertyit = entity.getProperties().iterator(); it.hasNext();) {
      Property prop = it.next();
      if ("uuid".equals(prop.getName())) {
        // Crop the UUID property
        it.remove();
      } else if (!prop.getEnclosingTypeName().equals(typeName)) {
        // Remove properties not declared in the current type
        it.remove();
      }
    }
    // Add the supertype
    addEntity(allEntitiesentity.getSupertype());
  }

  
If .concreteTypeMapFile is defined, load the file into concreteTypeMap.
  private void loadConcreteTypeMap() throws IOException {
    if ( != null) {
      JsonReader reader = new JsonReader(new InputStreamReader(new FileInputStream(
          ), ));
      reader.setLenient(true);
      reader.beginArray();
      while (reader.hasNext()) {
        .add(reader.nextString());
      }
      reader.endArray();
      reader.close();
    }
  }

  
Load java.stg from the classpath and configure a number of model adaptors to add virtual properties to the objects being rendered.
  private STGroup loadGroup() {
    STGroup group = new STGroupFile(getClass().getResource("java.stg"), "UTF8"'<''>');
    // EntityDescription are rendered as the FQN
      @Override
      public String toString(Object oString formatStringLocale locale) {
        EntityDescription entity = (EntityDescriptiono;
        if (entity.getTypeName().equals("baseHasUuid")) {
          // Swap out for our hand-written base class
          return entity.isPersistent() ? BasePersistenceAware.class.getCanonicalName()
              : BaseHasUuid.class.getCanonicalName();
        }
        return  + "." +  + upcase(entity.getTypeName());
      }
    });
    // Types are registered as FQPN
    group.registerRenderer(Type.classnew AttributeRenderer() {
      @Override
      public String toString(Object oString formatStringLocale locale) {
        Type type = (Typeo;
        return toString(type);
      }
      protected String toString(Type type) {
        // Allow a TypeHint to override any interpretation of the Type
        if (type.getTypeHint() != null) {
          return type.getTypeHint().getValue();
        }
        switch (type.getJsonKind()) {
          case :
            return JsonElement.class.getCanonicalName();
          case :
            return Boolean.class.getCanonicalName();
          case :
            return Double.class.getCanonicalName();
          case :
            return Integer.class.getCanonicalName();
          case :
            return List.class.getCanonicalName() + "<" + toString(type.getListElement()) + ">";
          case :
            return Map.class.getCanonicalName() + "<" + toString(type.getMapKey()) + ","
              + toString(type.getMapValue()) + ">";
          case :
            return Void.class.getCanonicalName();
          case : {
            // Look for the presence of enum values
            if (type.getEnumValues() != null) {
              // Register a referenced enum
              .add(type);
              return  + upcase(type.getName());
            }
            // Any other named type must be an entity type
            if (type.getName() != null) {
              // Allow type to be overridden
              return  + upcase(type.getName());
            }
            // Otherwise it must be a plain string
            return String.class.getCanonicalName();
          }
        }
        throw new UnsupportedOperationException("Unknown JsonKind " + type.getJsonKind());
      }
    });
      @Override
      public Object getProperty(Interpreter interpST selfObject oObject property,
          String propertyNamethrows STNoSuchPropertyException {
        EndpointDescription end = (EndpointDescriptiono;
        if ("combinedArgs".equals(propertyName)) {
          // Return the path and query parameters together
          List<ParameterDescriptiontoReturn = new ArrayList<ParameterDescription>();
          if (end.getPathParameters() != null) {
            toReturn.addAll(end.getPathParameters());
          }
          if (end.getQueryParameters() != null) {
            toReturn.addAll(end.getQueryParameters());
          }
          return toReturn;
        } else if ("javaName".equals(propertyName) || "javaNameUpcase".equals(propertyName)) {
          // Convert a path like /api/2/foo/bar/{}/baz to fooBarBazMethod
          String path = end.getPath();
          String[] parts = path.split(Pattern.quote("/"));
          StringBuilder sb = new StringBuilder();
          for (int i = j = parts.lengthi < ji++) {
            try {
              String part = parts[i];
              if (part.length() == 0) {
                continue;
              }
              StringBuilder decodedPart = new StringBuilder(URLDecoder.decode(part"UTF8"));
              // Trim characters that aren't legal
              for (int k = decodedPart.length() - 1; k >= 0; k--) {
                if (!Character.isJavaIdentifierPart(decodedPart.charAt(k))) {
                  decodedPart.deleteCharAt(k);
                }
              }
              // Append the new name part, using camel-cased names
              String newPart = decodedPart.toString();
              if (sb.length() > 0) {
                newPart = upcase(newPart);
              }
              sb.append(newPart);
            } catch (UnsupportedEncodingException e) {
              throw new RuntimeException(e);
            }
          }
          sb.append(upcase(end.getMethod().toLowerCase()));
          String javaName = sb.toString();
          if ("javaNameUpcase".equals(propertyName)) {
            javaName = upcase(javaName);
          }
          return javaName;
        } else if ("pathDecoded".equals(propertyName)) {
          // URL-decode the path in the endpoint description
          try {
            String decoded = URLDecoder.decode(end.getPath(), "UTF8");
            return decoded;
          } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
          }
        } else if ("hasPayload".equals(propertyName)) {
          return end.getEntity() != null;
        }
        return super.getProperty(interpselfopropertypropertyName);
      }
    });
      @Override
      public Object getProperty(Interpreter interpST selfObject oObject property,
          String propertyNamethrows STNoSuchPropertyException {
        EntityDescription entity = (EntityDescriptiono;
        if ("baseType".equals(propertyName)) {
          return .contains(entity.getTypeName());
        } else if ("payloadName".equals(propertyName)) {
          return entity.getTypeName();
        } else if ("supertype".equals(propertyName)) {
          EntityDescription supertype = entity.getSupertype();
          if (supertype == null) {
            return entity.isPersistent() ? BasePersistenceAware.class.getCanonicalName()
                : BaseHasUuid.class.getCanonicalName();
          } else {
            return supertype;
          }
        } else if ("simpleName".equals(propertyName)) {
          return  + upcase(entity.getTypeName());
        }
        return super.getProperty(interpselfopropertypropertyName);
      }
    });
      @Override
      public Object getProperty(Interpreter interpST selfObject oObject property,
          String propertyNamethrows STNoSuchPropertyException {
        ParameterDescription param = (ParameterDescriptiono;
        if ("javaNameUpcase".equals(propertyName)) {
          return upcase(param.getName());
        }
        return super.getProperty(interpselfopropertypropertyName);
      }
    });
    group.registerModelAdaptor(Property.classnew ObjectModelAdaptor() {
      @Override
      public Object getProperty(Interpreter interpST selfObject oObject property,
          String propertyNamethrows STNoSuchPropertyException {
        Property p = (Propertyo;
        if ("getterName".equals(propertyName)) {
          return upcase(p.getName());
        } else if ("getterPermitAll".equals(propertyName)) {
          return Collections.singleton("*").equals(p.getGetterRoleNames());
        } else if ("needsImplied".equals(propertyName)) {
          // Returns true if the property has @Implies / @OneToMany and is a list
          return p.getImpliedProperty() != null && p.getType().getListElement() != null;
        } else if ("setterPermitAll".equals(propertyName)) {
          return Collections.singleton("*").equals(p.getSetterRoleNames());
        }
        return super.getProperty(interpselfopropertypropertyName);
      }
    });
    group.registerModelAdaptor(Type.classnew ObjectModelAdaptor() {
      @Override
      public Object getProperty(Interpreter interpST selfObject oObject property,
          String propertyNamethrows STNoSuchPropertyException {
        Type type = (Typeo;
        if ("flatTypes".equals(propertyName)) {
          return flatten(type);
        }
        return super.getProperty(interpselfopropertypropertyName);
      }
      private List<Stringflatten(Type type) {
        switch (type.getJsonKind()) {
          case :
            return Collections.singletonList(Object.class.getCanonicalName());
          case :
            return Collections.singletonList(Boolean.class.getCanonicalName());
          case :
            return Collections.singletonList(Double.class.getCanonicalName());
          case :
            return Collections.singletonList(Integer.class.getCanonicalName());
          case : {
            List<StringtoReturn = new ArrayList<String>();
            toReturn.add(List.class.getCanonicalName());
            toReturn.addAll(flatten(type.getListElement()));
            return toReturn;
          }
          case : {
            List<StringtoReturn = new ArrayList<String>();
            toReturn.add(Map.class.getCanonicalName());
            toReturn.addAll(flatten(type.getMapKey()));
            toReturn.addAll(flatten(type.getMapValue()));
            return toReturn;
          }
          case :
            return Collections.singletonList(Void.class.getCanonicalName());
          case : {
            if (type.getName() != null) {
              return Collections.singletonList( + upcase(type.getName()));
            } else if (type.getTypeHint() != null) {
              return Collections.singletonList(type.getTypeHint().getValue());
            } else {
              return Collections.singletonList(String.class.getCanonicalName());
            }
          }
        }
        throw new UnsupportedOperationException("Unknown JsonKind " + type.getJsonKind());
      }
    });
    group.registerModelAdaptor(String.classnew ObjectModelAdaptor() {
      @Override
      public Object getProperty(Interpreter interpST selfObject oObject property,
          String propertyNamethrows STNoSuchPropertyException {
        final String string = (Stringo;
        if ("chunks".equals(propertyName)) {
          /*
           * Split a string into individual chunks that can be reflowed. This implementation is
           * pretty simplistic, but helps make the generated documentation at least somewhat more
           * readable.
           */
          return new Iterator<CharSequence>() {
            int index;
            int length = string.length();
            CharSequence next;
            {
              advance();
            }
            @Override
            public boolean hasNext() {
              return  != null;
            }
            @Override
            public CharSequence next() {
              CharSequence toReturn = ;
              advance();
              return toReturn;
            }
            @Override
            public void remove() {
              throw new UnsupportedOperationException();
            }
            private void advance() {
              int start = advance(false);
              int end = advance(true);
              if (start == end) {
                 = null;
              } else {
                 = string.subSequence(startend);
              }
            }

            
Advance to next non-whitespace character.
            private int advance(boolean whitespace) {
              while ( < 
                && (whitespace ^ Character.isWhitespace(string.charAt()))) {
                ++;
              }
              return ;
            }
          };
        }
        return super.getProperty(interpselfopropertypropertyName);
      }
    });
    Map<StringObjectnamesMap = new HashMap<StringObject>();
    for (Class<?> clazz : ) {
      namesMap.put(clazz.getSimpleName(), clazz.getCanonicalName());
    }
    group.defineDictionary("names"namesMap);
    return group;
  }
  private void render(ST enumSTFile packageDirString typeNamethrows IOException {
    Writer fileWriter = new OutputStreamWriter(
        new FileOutputStream(new File(packageDirtypeName + ".java")), );
    AutoIndentWriter writer = new AutoIndentWriter(fileWriter);
    writer.setLineWidth(80);
    enumST.write(writer);
    fileWriter.close();
  }
New to GrepCode? Check out our FAQ X