| Index: plugins/org.chromium.sdk.wipbackend.wk120709/src-dynamic-impl/parser/org/chromium/sdk/internal/wip/tools/protocolgenerator/Generator.java
|
| diff --git a/plugins/org.chromium.sdk.wipbackend.wk120709/src-dynamic-impl/parser/org/chromium/sdk/internal/wip/tools/protocolgenerator/Generator.java b/plugins/org.chromium.sdk.wipbackend.wk120709/src-dynamic-impl/parser/org/chromium/sdk/internal/wip/tools/protocolgenerator/Generator.java
|
| deleted file mode 100644
|
| index 798c177eff24d6be4e0e08e8a0690f06190e7636..0000000000000000000000000000000000000000
|
| --- a/plugins/org.chromium.sdk.wipbackend.wk120709/src-dynamic-impl/parser/org/chromium/sdk/internal/wip/tools/protocolgenerator/Generator.java
|
| +++ /dev/null
|
| @@ -1,2079 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package org.chromium.sdk.internal.wip.tools.protocolgenerator;
|
| -
|
| -import java.io.File;
|
| -import java.io.IOException;
|
| -import java.io.Writer;
|
| -import java.util.ArrayList;
|
| -import java.util.Arrays;
|
| -import java.util.Collection;
|
| -import java.util.Collections;
|
| -import java.util.HashMap;
|
| -import java.util.HashSet;
|
| -import java.util.List;
|
| -import java.util.Map;
|
| -import java.util.Set;
|
| -
|
| -import org.chromium.sdk.internal.protocolparser.EnumValueCondition;
|
| -import org.chromium.sdk.internal.wip.tools.protocolgenerator.WipMetamodel.ArrayItemType;
|
| -import org.chromium.sdk.internal.wip.tools.protocolgenerator.WipMetamodel.Command;
|
| -import org.chromium.sdk.internal.wip.tools.protocolgenerator.WipMetamodel.Domain;
|
| -import org.chromium.sdk.internal.wip.tools.protocolgenerator.WipMetamodel.Event;
|
| -import org.chromium.sdk.internal.wip.tools.protocolgenerator.WipMetamodel.ObjectProperty;
|
| -import org.chromium.sdk.internal.wip.tools.protocolgenerator.WipMetamodel.Parameter;
|
| -import org.chromium.sdk.internal.wip.tools.protocolgenerator.WipMetamodel.StandaloneType;
|
| -
|
| -/**
|
| - * Read metamodel and generates set of files with Java classes/interfaces for the protocol.
|
| - */
|
| -class Generator {
|
| - private static final String ROOT_PACKAGE = "org.chromium.sdk.internal.wip.protocol";
|
| - private static final String OUTPUT_PACKAGE = ROOT_PACKAGE + ".output";
|
| - private static final String INPUT_PACKAGE = ROOT_PACKAGE + ".input";
|
| - private static final String COMMON_PACKAGE = ROOT_PACKAGE + ".common";
|
| - private static final String PARSER_INTERFACE_LIST_CLASS_NAME = "GeneratedParserInterfaceList";
|
| - private static final String PARSER_ROOT_INTERFACE_NAME = "WipGeneratedParserRoot";
|
| -
|
| - private final List<String> jsonProtocolParserClassNames = new ArrayList<String>();
|
| - private final List<ParserRootInterfaceItem> parserRootInterfaceItems =
|
| - new ArrayList<ParserRootInterfaceItem>();
|
| - private final TypeMap typeMap = new TypeMap();
|
| - private final String originReference;
|
| -
|
| - private final FileSet fileSet;
|
| -
|
| - Generator(String outputDir, String originReference) {
|
| - this.originReference = originReference;
|
| - this.fileSet = new FileSet(new File(outputDir));
|
| - }
|
| -
|
| - void go(WipMetamodel.Root metamodel) throws IOException {
|
| - List<Domain> domainList = metamodel.domains();
|
| -
|
| - initializeKnownTypes(typeMap);
|
| -
|
| - Set<String> domainTodoList = new HashSet<String>(Arrays.asList(DOMAIN_WHITE_LIST));
|
| -
|
| - Map<String, DomainGenerator> domainGeneratorMap =
|
| - new HashMap<String, Generator.DomainGenerator>();
|
| -
|
| - for (Domain domain : domainList) {
|
| - boolean found = domainTodoList.remove(domain.domain());
|
| - if (!found) {
|
| - System.out.println("Domain skipped: " + domain.domain());
|
| - continue;
|
| - }
|
| -
|
| - DomainGenerator domainGenerator = new DomainGenerator(domain);
|
| - domainGeneratorMap.put(domain.domain(), domainGenerator);
|
| -
|
| - domainGenerator.registerTypes();
|
| - }
|
| -
|
| - typeMap.setDomainGeneratorMap(domainGeneratorMap);
|
| -
|
| - if (!domainTodoList.isEmpty()) {
|
| - throw new RuntimeException("Domains expected but not found: " + domainTodoList);
|
| - }
|
| -
|
| - for (DomainGenerator domainGenerator : domainGeneratorMap.values()) {
|
| - domainGenerator.generateCommandsAndEvents();
|
| - }
|
| -
|
| - typeMap.generateRequestedTypes();
|
| -
|
| - generateParserInterfaceList();
|
| -
|
| - generateParserRoot(parserRootInterfaceItems);
|
| -
|
| - fileSet.deleteOtherFiles();
|
| - }
|
| -
|
| - private class DomainGenerator {
|
| - private final Domain domain;
|
| -
|
| - DomainGenerator(Domain domain) {
|
| - this.domain = domain;
|
| - }
|
| -
|
| - void registerTypes() {
|
| - if (domain.types() != null) {
|
| - for (StandaloneType type : domain.types()) {
|
| - typeMap.getTypeData(domain.domain(), type.id()).setType(type);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void generateCommandsAndEvents() throws IOException {
|
| - for (Command command : domain.commands()) {
|
| - boolean hasResponse = command.returns() != null;
|
| - generateCommandParams(command, hasResponse);
|
| - if (hasResponse) {
|
| - generateCommandData(command);
|
| - String dataFullName = Naming.COMMAND_DATA.getFullName(domain.domain(),
|
| - command.name()).getFullText();
|
| - jsonProtocolParserClassNames.add(dataFullName);
|
| - parserRootInterfaceItems.add(
|
| - new ParserRootInterfaceItem(domain.domain(), command.name(), Naming.COMMAND_DATA));
|
| - }
|
| - }
|
| -
|
| - if (domain.events() != null) {
|
| - for (Event event : domain.events()) {
|
| - generateEvenData(event);
|
| - jsonProtocolParserClassNames.add(
|
| - Naming.EVENT_DATA.getFullName(domain.domain(), event.name()).getFullText());
|
| - parserRootInterfaceItems.add(
|
| - new ParserRootInterfaceItem(domain.domain(), event.name(), Naming.EVENT_DATA));
|
| - }
|
| - }
|
| - }
|
| -
|
| - private void generateCommandParams(Command command, boolean hasResponse) throws IOException {
|
| - StringBuilder baseTypeBuilder = new StringBuilder();
|
| - baseTypeBuilder.append("org.chromium.sdk.internal.wip.protocol.output.");
|
| - if (hasResponse) {
|
| - baseTypeBuilder.append("WipParamsWithResponse<" +
|
| - Naming.COMMAND_DATA.getFullName(domain.domain(), command.name()).getFullText() + ">");
|
| - } else {
|
| - baseTypeBuilder.append("WipParams");
|
| - }
|
| -
|
| - DeferredWriter additionalMemberBuilder = new DeferredWriter();
|
| - additionalMemberBuilder.append("\t public static final String METHOD_NAME = " +
|
| - "org.chromium.sdk.internal.wip.protocol.BasicConstants.Domain." +
|
| - domain.domain().toUpperCase() + " + \"." + command.name() + "\";\n");
|
| - additionalMemberBuilder.append("\n");
|
| -
|
| -
|
| - additionalMemberBuilder.append("\t @Override protected String getRequestName() {\n");
|
| - additionalMemberBuilder.append("\t return METHOD_NAME;\n");
|
| - additionalMemberBuilder.append("\t }\n");
|
| - additionalMemberBuilder.append("\t\n");
|
| -
|
| - if (hasResponse) {
|
| - String dataInterfaceFullname =
|
| - Naming.COMMAND_DATA.getFullName(domain.domain(), command.name()).getFullText();
|
| - additionalMemberBuilder.append(
|
| - "\t @Override public " + dataInterfaceFullname + " parseResponse(" +
|
| - "org.chromium.sdk.internal.wip.protocol.input.WipCommandResponse.Data data, " +
|
| - "org.chromium.sdk.internal.wip.protocol.input." +
|
| - PARSER_ROOT_INTERFACE_NAME + " parser) " +
|
| - "throws org.chromium.sdk.internal.protocolparser.JsonProtocolParseException {\n");
|
| - additionalMemberBuilder.append("\t return parser." +
|
| - Naming.COMMAND_DATA.getParseMethodName(domain.domain(), command.name()) +
|
| - "(data.getUnderlyingObject());\n");
|
| - additionalMemberBuilder.append("\t }\n");
|
| - additionalMemberBuilder.append("\t\n");
|
| - }
|
| -
|
| - generateTopLevelOutputClass(Naming.PARAMS, command.name(), command.description(),
|
| - baseTypeBuilder.toString(), additionalMemberBuilder, command.parameters(),
|
| - PropertyLikeAccess.PARAMETER);
|
| - }
|
| -
|
| - private void generateCommandAdditionalParam(StandaloneType type) throws IOException {
|
| - generateTopLevelOutputClass(Naming.ADDITIONAL_PARAM, type.id(), type.description(),
|
| - "org.json.simple.JSONObject", null, type.properties(), PropertyLikeAccess.PROPERTY);
|
| - }
|
| -
|
| - private <P> void generateTopLevelOutputClass(ClassNameScheme nameScheme, String baseName,
|
| - String description, String baseType, DeferredWriter additionalMemberText,
|
| - List<P> properties, PropertyLikeAccess<P> propertyAccess) throws IOException {
|
| - JavaFileUpdater fileUpdater = startJavaFile(nameScheme, domain, baseName);
|
| -
|
| - Writer writer = fileUpdater.getWriter();
|
| - IndentWriter indentWriter = new IndentWriterImpl(writer, "");
|
| -
|
| - NamePath classNamePath = nameScheme.getFullName(domain.domain(), baseName);
|
| -
|
| - generateOutputClass(indentWriter, classNamePath, description, baseType, additionalMemberText,
|
| - properties, propertyAccess);
|
| -
|
| - writer.close();
|
| -
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - private <P> void generateOutputClass(IndentWriter writer, NamePath classNamePath,
|
| - String description, String baseType, DeferredWriter additionalMemberText,
|
| - List<P> properties, PropertyLikeAccess<P> propertyAccess) throws IOException {
|
| - if (description != null) {
|
| - writer.append("\t/**\n" + description + "\n */\n");
|
| - }
|
| - writer.append("\tpublic class " + classNamePath.getLastComponent() +
|
| - " extends " + baseType + " {\n");
|
| -
|
| - OutputClassScope classScope = new OutputClassScope(classNamePath);
|
| -
|
| - if (additionalMemberText != null) {
|
| - classScope.addMember("param-specific", additionalMemberText);
|
| - }
|
| -
|
| - classScope.generateCommandParamsBody(writer, properties, propertyAccess,
|
| - classNamePath.getLastComponent());
|
| -
|
| - classScope.writeAdditionalMembers(writer);
|
| -
|
| - writer.append("\t}\n");
|
| - }
|
| -
|
| - abstract class CreateStandalonTypeBindingVisitorBase implements
|
| - TypeVisitor<StandaloneTypeBinding> {
|
| - private final StandaloneType type;
|
| -
|
| - CreateStandalonTypeBindingVisitorBase(StandaloneType type) {
|
| - this.type = type;
|
| - }
|
| -
|
| - protected StandaloneType getType() {
|
| - return type;
|
| - }
|
| -
|
| - @Override public StandaloneTypeBinding visitString() {
|
| - return createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.STRING,
|
| - Naming.COMMON_TYPEDEF, null);
|
| - }
|
| - @Override public StandaloneTypeBinding visitInteger() {
|
| - return createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.LONG,
|
| - Naming.COMMON_TYPEDEF, null);
|
| - }
|
| - @Override public StandaloneTypeBinding visitRef(String refName) {
|
| - throw new RuntimeException();
|
| - }
|
| - @Override public StandaloneTypeBinding visitBoolean() {
|
| - throw new RuntimeException();
|
| - }
|
| - @Override public StandaloneTypeBinding visitNumber() {
|
| - return createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.NUMBER,
|
| - Naming.COMMON_TYPEDEF, null);
|
| - }
|
| - @Override public StandaloneTypeBinding visitUnknown() {
|
| - throw new RuntimeException();
|
| - }
|
| - }
|
| -
|
| - StandaloneTypeBinding createStandaloneOutputTypeBinding(StandaloneType type,
|
| - final String name) {
|
| - return switchByType(type, TypedObjectAccess.FOR_STANDALONE,
|
| - new CreateStandalonTypeBindingVisitorBase(type) {
|
| - @Override
|
| - public StandaloneTypeBinding visitObject(List<ObjectProperty> properties) {
|
| - return new StandaloneTypeBinding() {
|
| - @Override
|
| - public BoxableType getJavaType() {
|
| - return BoxableType.createReference(
|
| - Naming.ADDITIONAL_PARAM.getFullName(domain.domain(), name));
|
| - }
|
| -
|
| - @Override public void generate() throws IOException {
|
| - generateCommandAdditionalParam(getType());
|
| - }
|
| -
|
| - @Override public TypeData.Direction getDirection() {
|
| - return TypeData.Direction.OUTPUT;
|
| - }
|
| - };
|
| - }
|
| -
|
| - @Override
|
| - public StandaloneTypeBinding visitEnum(List<String> enumConstants) {
|
| - throw new RuntimeException();
|
| - }
|
| - @Override public StandaloneTypeBinding visitArray(final ArrayItemType items) {
|
| -
|
| - StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() {
|
| - @Override
|
| - public BoxableType resolve(final ResolveContext context) {
|
| - ResolveAndGenerateScope resolveAndGenerateScope = new ResolveAndGenerateScope() {
|
| - // This class is responsible for generating ad hoc type.
|
| - // If we ever are to do it, we should generate into string buffer and put strings
|
| - // inside TypeDef class.
|
| - @Override public String getDomainName() {
|
| - return domain.domain();
|
| - }
|
| - @Override public TypeData.Direction getTypeDirection() {
|
| - return TypeData.Direction.OUTPUT;
|
| - }
|
| - @Override public BoxableType generateEnum(String description,
|
| - List<String> enumConstants) {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| -
|
| - @Override
|
| - public <T> QualifiedTypeData resolveType(T typedObject,
|
| - Generator.TypedObjectAccess<T> access) {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| - @Override
|
| - public BoxableType generateNestedObject(String description,
|
| - List<ObjectProperty> properties) throws IOException {
|
| - return context.generateNestedObject("Item", description, properties);
|
| - }
|
| - };
|
| - QualifiedTypeData itemTypeData =
|
| - resolveType(items, TypedObjectAccess.FOR_ARRAY_ITEM, resolveAndGenerateScope);
|
| - BoxableType itemBoxableType = itemTypeData.getJavaType();
|
| -
|
| - final BoxableType arrayType = BoxableType.createList(itemBoxableType);
|
| -
|
| - return arrayType;
|
| - }
|
| - };
|
| -
|
| - return createTypedefTypeBinding(getType(), target,
|
| - Naming.OUTPUT_TYPEDEF, TypeData.Direction.OUTPUT);
|
| - }
|
| - });
|
| - }
|
| -
|
| - StandaloneTypeBinding createStandaloneInputTypeBinding(StandaloneType type) {
|
| - return switchByType(type, TypedObjectAccess.FOR_STANDALONE,
|
| - new CreateStandalonTypeBindingVisitorBase(type) {
|
| - @Override
|
| - public StandaloneTypeBinding visitObject(List<ObjectProperty> properties) {
|
| - return createStandaloneObjectInputTypeBinding(getType(), properties);
|
| - }
|
| -
|
| - @Override
|
| - public StandaloneTypeBinding visitEnum(List<String> enumConstants) {
|
| - return createStandaloneEnumInputTypeBinding(getType(), enumConstants,
|
| - TypeData.Direction.INPUT);
|
| - }
|
| -
|
| - @Override public StandaloneTypeBinding visitArray(ArrayItemType items) {
|
| - ResolveAndGenerateScope resolveAndGenerateScope = new ResolveAndGenerateScope() {
|
| - // This class is responsible for generating ad hoc type.
|
| - // If we ever are to do it, we should generate into string buffer and put strings
|
| - // inside TypeDef class.
|
| - @Override public String getDomainName() {
|
| - return domain.domain();
|
| - }
|
| - @Override public TypeData.Direction getTypeDirection() {
|
| - return TypeData.Direction.INPUT;
|
| - }
|
| - @Override public BoxableType generateEnum(String description,
|
| - List<String> enumConstants) {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| -
|
| - @Override
|
| - public <T> QualifiedTypeData resolveType(T typedObject,
|
| - Generator.TypedObjectAccess<T> access) {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| - @Override
|
| - public BoxableType generateNestedObject(String description,
|
| - List<ObjectProperty> properties) throws IOException {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| - };
|
| - QualifiedTypeData itemTypeData =
|
| - resolveType(items, TypedObjectAccess.FOR_ARRAY_ITEM, resolveAndGenerateScope);
|
| - BoxableType itemBoxableType = itemTypeData.getJavaType();
|
| -
|
| - final BoxableType arrayType = BoxableType.createList(itemBoxableType);
|
| -
|
| - StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() {
|
| - @Override
|
| - public BoxableType resolve(ResolveContext context) {
|
| - return arrayType;
|
| - }
|
| - };
|
| -
|
| - return createTypedefTypeBinding(getType(), target,
|
| - Naming.INPUT_TYPEDEF, TypeData.Direction.INPUT);
|
| - }
|
| - });
|
| - }
|
| -
|
| - StandaloneTypeBinding createStandaloneObjectInputTypeBinding(final StandaloneType type,
|
| - final List<ObjectProperty> properties) {
|
| - final String name = type.id();
|
| - final NamePath fullTypeName = Naming.INPUT_VALUE.getFullName(domain.domain(), name);
|
| - jsonProtocolParserClassNames.add(fullTypeName.getFullText());
|
| -
|
| - return new StandaloneTypeBinding() {
|
| - @Override public BoxableType getJavaType() {
|
| - return BoxableType.createReference(fullTypeName);
|
| - }
|
| -
|
| - @Override
|
| - public void generate() throws IOException {
|
| - String description = type.description();
|
| -
|
| - NamePath className = Naming.INPUT_VALUE.getFullName(domain.domain(), name);
|
| - JavaFileUpdater fileUpdater = startJavaFile(Naming.INPUT_VALUE, domain, name);
|
| -
|
| - IndentWriter writer = new IndentWriterImpl(fileUpdater.getWriter(), "");
|
| -
|
| - if (description != null) {
|
| - writer.append("\t/**\n " + description + "\n */\n");
|
| - }
|
| -
|
| - writer.append("\t@org.chromium.sdk.internal.protocolparser.JsonType\n");
|
| - writer.append("\tpublic interface " + className.getLastComponent() +" {\n");
|
| -
|
| - InputClassScope classScope = new InputClassScope(className);
|
| -
|
| - classScope.generateStandaloneTypeBody(writer, properties);
|
| -
|
| - classScope.writeAdditionalMembers(writer);
|
| -
|
| - writer.append("\t}\n");
|
| -
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - @Override public TypeData.Direction getDirection() {
|
| - return TypeData.Direction.INPUT;
|
| - }
|
| - };
|
| - }
|
| -
|
| - StandaloneTypeBinding createStandaloneEnumInputTypeBinding(final StandaloneType type,
|
| - final List<String> enumConstants, final TypeData.Direction direction) {
|
| - final String name = type.id();
|
| - return new StandaloneTypeBinding() {
|
| - @Override public BoxableType getJavaType() {
|
| - return BoxableType.createReference(Naming.INPUT_ENUM.getFullName(domain.domain(), name));
|
| - }
|
| -
|
| - @Override
|
| - public void generate() throws IOException {
|
| - String description = type.description();
|
| -
|
| - String className = Naming.INPUT_ENUM.getShortName(name);
|
| - JavaFileUpdater fileUpdater = startJavaFile(Naming.INPUT_ENUM, domain, name);
|
| -
|
| - Writer writer = fileUpdater.getWriter();
|
| -
|
| - if (description != null) {
|
| - writer.write("/**\n " + description + "\n */\n");
|
| - }
|
| -
|
| - writer.write("public enum " + className +" {\n");
|
| -
|
| - boolean first = true;
|
| - for (String constName : enumConstants) {
|
| - if (first) {
|
| - writer.write("\n ");
|
| - } else {
|
| - writer.write(",\n ");
|
| - }
|
| - writer.write(EnumValueCondition.decorateEnumConstantName(constName));
|
| - first = false;
|
| - }
|
| - writer.write("\n");
|
| -
|
| - writer.write("}\n");
|
| -
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - @Override public TypeData.Direction getDirection() {
|
| - return direction;
|
| - }
|
| - };
|
| - }
|
| -
|
| - /**
|
| - * Typedef is an empty class that just holds description and
|
| - * refers to an actual type (such as String).
|
| - */
|
| - StandaloneTypeBinding createTypedefTypeBinding(final StandaloneType type,
|
| - StandaloneTypeBinding.Target target,
|
| - final ClassNameScheme nameScheme, final TypeData.Direction direction) {
|
| - final String name = type.id();
|
| - final NamePath typedefJavaName = nameScheme.getFullName(domain.domain(), name);
|
| - final BoxableType typedefJavaType = BoxableType.createReference(typedefJavaName);
|
| -
|
| - final List<DeferredWriter> deferredWriters = new ArrayList<Generator.DeferredWriter>(0);
|
| -
|
| - class ResolveContextImpl implements StandaloneTypeBinding.Target.ResolveContext {
|
| - @Override
|
| - public BoxableType generateNestedObject(String shortName,
|
| - String description, List<ObjectProperty> properties)
|
| - throws IOException {
|
| -
|
| - DeferredWriter writer = new DeferredWriter();
|
| -
|
| - NamePath classNamePath = new NamePath(shortName, typedefJavaName);
|
| -
|
| - if (direction == null) {
|
| - throw new RuntimeException("Unsupported");
|
| - } else {
|
| - switch (direction) {
|
| - case INPUT:
|
| - throw new RuntimeException("TODO");
|
| - case OUTPUT:
|
| - generateOutputClass(writer, classNamePath, description, "org.json.simple.JSONObject",
|
| - null, properties, PropertyLikeAccess.PROPERTY);
|
| - break;
|
| - default:
|
| - throw new RuntimeException();
|
| - }
|
| - }
|
| -
|
| - deferredWriters.add(writer);
|
| -
|
| - return BoxableType.createReference(new NamePath(shortName, typedefJavaName));
|
| - }
|
| - }
|
| -
|
| - ResolveContextImpl resolveContext = new ResolveContextImpl();
|
| -
|
| - final BoxableType actualJavaType = target.resolve(resolveContext);
|
| -
|
| - return new StandaloneTypeBinding() {
|
| - @Override public BoxableType getJavaType() {
|
| - return new DecoratedBoxableType(actualJavaType);
|
| - }
|
| -
|
| - class DecoratedBoxableType extends BoxableType {
|
| - private final BoxableType original;
|
| -
|
| - DecoratedBoxableType(BoxableType original) {
|
| - this.original = original;
|
| - }
|
| - @Override String getFullText() {
|
| - return decorateTypeName(original.getFullText(), typedefJavaType.getFullText());
|
| - }
|
| - @Override String getShortText(NamePath contextNamespace) {
|
| - return decorateTypeName(original.getShortText(contextNamespace),
|
| - typedefJavaType.getShortText(contextNamespace));
|
| - }
|
| - @Override BoxableType convertToPureReference() {
|
| - BoxableType pureReference = original.convertToPureReference();
|
| - if (pureReference == original) {
|
| - return this;
|
| - } else {
|
| - return new DecoratedBoxableType(pureReference);
|
| - }
|
| - }
|
| - private String decorateTypeName(String actualTypeName, String innerTypeName) {
|
| - return actualTypeName + "/*See " + innerTypeName + "*/";
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void generate() throws IOException {
|
| - String description = type.description();
|
| -
|
| - String className = nameScheme.getShortName(name);
|
| - JavaFileUpdater fileUpdater = startJavaFile(nameScheme, domain, name);
|
| -
|
| - NamePath contextNamespace = typedefJavaName;
|
| -
|
| - IndentWriter writer = new IndentWriterImpl(fileUpdater.getWriter(), "");
|
| -
|
| - if (description != null) {
|
| - writer.append("\t/**\n " + description + "\n */\n");
|
| - }
|
| -
|
| - writer.append("\tpublic class " + className + " {\n");
|
| - writer.append("\t /*\n The class is 'typedef'.\n" +
|
| - "\t It merely holds a type javadoc and its only field refers to an " +
|
| - "actual type.\n" +
|
| - "\t */\n");
|
| - writer.append("\t " + actualJavaType.getShortText(contextNamespace) + " actualType;\n");
|
| -
|
| - IndentWriter innerWriter = writer.createInner();
|
| - for (DeferredWriter memberWriter : deferredWriters) {
|
| - memberWriter.writeContent(innerWriter);
|
| - }
|
| -
|
| - writer.append("\t}\n");
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - @Override public TypeData.Direction getDirection() {
|
| - return direction;
|
| - }
|
| - };
|
| - }
|
| -
|
| - private void generateCommandData(Command command) throws IOException {
|
| - String className = Naming.COMMAND_DATA.getShortName(command.name());
|
| - JavaFileUpdater fileUpdater = startJavaFile(Naming.COMMAND_DATA, domain, command.name());
|
| -
|
| - IndentWriter writer = new IndentWriterImpl(fileUpdater.getWriter(), "");
|
| -
|
| - generateJsonProtocolInterface(writer, className, command.description(),
|
| - command.returns(), null);
|
| -
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - private void generateEvenData(Event event) throws IOException {
|
| - String className = Naming.EVENT_DATA.getShortName(event.name());
|
| - JavaFileUpdater fileUpdater = startJavaFile(Naming.EVENT_DATA, domain, event.name());
|
| - String domainName = domain.domain();
|
| - String fullName = Naming.EVENT_DATA.getFullName(domainName, event.name()).getFullText();
|
| -
|
| - DeferredWriter eventTypeMemberText = new DeferredWriter();
|
| - eventTypeMemberText.append(
|
| - "\t public static final org.chromium.sdk.internal.wip.protocol.input.WipEventType<" +
|
| - fullName +
|
| - "> TYPE\n\t = new org.chromium.sdk.internal.wip.protocol.input.WipEventType<" +
|
| - fullName +
|
| - ">(\"" + domainName + "." + event.name() + "\", " + fullName + ".class) {\n" +
|
| - "\t @Override public " + fullName + " parse(" + INPUT_PACKAGE + "." +
|
| - PARSER_ROOT_INTERFACE_NAME + " parser, org.json.simple.JSONObject obj)" +
|
| - " throws org.chromium.sdk.internal.protocolparser.JsonProtocolParseException {\n" +
|
| - "\t return parser." +
|
| - Naming.EVENT_DATA.getParseMethodName(domainName, event.name()) +
|
| - "(obj);\n" +
|
| - "\t }\n" +
|
| - "\t };\n");
|
| -
|
| - IndentWriter writer = new IndentWriterImpl(fileUpdater.getWriter(), "");
|
| -
|
| - generateJsonProtocolInterface(writer, className, event.description(), event.parameters(),
|
| - eventTypeMemberText);
|
| -
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - private void generateJsonProtocolInterface(IndentWriter writer, String className,
|
| - String description, List<Parameter> parameters, DeferredWriter additionalMembersText)
|
| - throws IOException {
|
| - if (description != null) {
|
| - writer.append("\t/**\n " + description + "\n */\n");
|
| - }
|
| -
|
| - writer.append("\t@org.chromium.sdk.internal.protocolparser.JsonType\n");
|
| - writer.append("\tpublic interface " + className +" {\n");
|
| -
|
| - InputClassScope classScope = new InputClassScope(new NamePath(className,
|
| - new NamePath(ClassNameScheme.Input.getPackageName(domain.domain()))));
|
| -
|
| - if (additionalMembersText != null) {
|
| - classScope.addMember("extra", additionalMembersText);
|
| - }
|
| -
|
| - classScope.generateMainJsonProtocolInterfaceBody(writer, parameters);
|
| -
|
| - classScope.writeAdditionalMembers(writer);
|
| -
|
| - writer.append("\t}\n");
|
| - }
|
| -
|
| - private abstract class ClassScope {
|
| - private final List<DeferredWriter> additionalMemberTexts = new ArrayList<DeferredWriter>(2);
|
| - private final NamePath contextNamespace;
|
| -
|
| - ClassScope(NamePath classNamespace) {
|
| - this.contextNamespace = classNamespace;
|
| - }
|
| -
|
| - protected String getShortClassName() {
|
| - return contextNamespace.getLastComponent();
|
| - }
|
| -
|
| - String getFullName() {
|
| - return contextNamespace.getFullText();
|
| - }
|
| -
|
| - NamePath getClassContextNamespace() {
|
| - return contextNamespace;
|
| - }
|
| -
|
| - void addMember(String key, DeferredWriter deferredWriter) {
|
| - additionalMemberTexts.add(deferredWriter);
|
| - }
|
| -
|
| - void writeAdditionalMembers(IndentWriter writer) throws IOException {
|
| - for (DeferredWriter deferredWriter : additionalMemberTexts) {
|
| - deferredWriter.writeContent(writer);
|
| - }
|
| - }
|
| -
|
| - protected abstract MemberScope newMemberScope(String memberName);
|
| - protected abstract TypeData.Direction getTypeDirection();
|
| -
|
| - /**
|
| - * Member scope is used to generate additional types that are used only from method.
|
| - * These types will be named after this method.
|
| - */
|
| - protected abstract class MemberScope implements ResolveAndGenerateScope {
|
| - private final String memberName;
|
| -
|
| - protected MemberScope(String memberName) {
|
| - this.memberName = memberName;
|
| - }
|
| -
|
| - private QualifiedTypeData resolveType(ObjectProperty objectProperty) {
|
| - return resolveType(objectProperty, TypedObjectAccess.FOR_OBJECT_PROPERTY);
|
| - }
|
| -
|
| - private QualifiedTypeData resolveType(Parameter parameter) {
|
| - return resolveType(parameter, TypedObjectAccess.FOR_PARAMETER);
|
| - }
|
| -
|
| - @Override
|
| - public <T> QualifiedTypeData resolveType(T typedObject, TypedObjectAccess<T> access) {
|
| - return Generator.this.resolveType(typedObject, access, this);
|
| - }
|
| -
|
| - protected String getMemberName() {
|
| - return memberName;
|
| - }
|
| -
|
| - public abstract BoxableType generateEnum(String description, List<String> enumConstants);
|
| - public abstract BoxableType generateNestedObject(String description,
|
| - List<ObjectProperty> propertyList) throws IOException;
|
| -
|
| - @Override
|
| - public String getDomainName() {
|
| - return domain.domain();
|
| - }
|
| -
|
| - @Override
|
| - public TypeData.Direction getTypeDirection() {
|
| - return ClassScope.this.getTypeDirection();
|
| - }
|
| - }
|
| - }
|
| -
|
| - class InputClassScope extends ClassScope {
|
| - InputClassScope(NamePath namePath) {
|
| - super(namePath);
|
| - }
|
| -
|
| - public void generateMainJsonProtocolInterfaceBody(IndentWriter writer,
|
| - List<Parameter> parameters) throws IOException {
|
| - if (parameters != null) {
|
| - for (Parameter param : parameters) {
|
| - if (param.description() != null) {
|
| - writer.append("\t /**\n " + param.description() + "\n */\n");
|
| - }
|
| -
|
| - String methodName = generateMethodNameSubstitute(param.name(), writer);
|
| -
|
| - ClassScope.MemberScope memberScope = newMemberScope(param.name());
|
| -
|
| - QualifiedTypeData paramTypeData = memberScope.resolveType(param);
|
| -
|
| - paramTypeData.writeAnnotations(writer, " ");
|
| -
|
| - writer.append("\t " +
|
| - paramTypeData.getJavaType().getShortText(getClassContextNamespace()) + " " +
|
| - methodName + "();\n");
|
| - writer.append("\t\n");
|
| - }
|
| - }
|
| - }
|
| -
|
| - void generateStandaloneTypeBody(IndentWriter writer, List<ObjectProperty> properties)
|
| - throws IOException {
|
| - if (properties != null) {
|
| - for (ObjectProperty objectProperty : properties) {
|
| - String propertyName = objectProperty.name();
|
| -
|
| - if (objectProperty.description() != null) {
|
| - writer.append("\t /**\n " + objectProperty.description() + "\n */\n");
|
| - }
|
| -
|
| - String methodName = generateMethodNameSubstitute(propertyName, writer);
|
| -
|
| - ClassScope.MemberScope memberScope = newMemberScope(propertyName);
|
| -
|
| - QualifiedTypeData propertyTypeData = memberScope.resolveType(objectProperty);
|
| -
|
| - propertyTypeData.writeAnnotations(writer, " ");
|
| -
|
| - writer.append("\t " +
|
| - propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + " " +
|
| - methodName + "();\n");
|
| - writer.append("\t\n");
|
| - }
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - protected TypeData.Direction getTypeDirection() {
|
| - return TypeData.Direction.INPUT;
|
| - }
|
| -
|
| - @Override
|
| - protected MemberScope newMemberScope(String memberName) {
|
| - return new InputMemberScope(memberName);
|
| - }
|
| -
|
| - class InputMemberScope extends MemberScope {
|
| - InputMemberScope(String memberName) {
|
| - super(memberName);
|
| - }
|
| -
|
| - @Override
|
| - public BoxableType generateEnum(String description, List<String> enumConstants) {
|
| - DeferredWriter builder = new DeferredWriter();
|
| - if (description != null) {
|
| - builder.append("\t /**\n " + description + "\n */\n");
|
| - }
|
| -
|
| - String enumName = capitalizeFirstChar(getMemberName());
|
| - builder.append("\t public enum " + enumName + " {\n");
|
| - for (String constant : enumConstants) {
|
| - builder.append("\t " +
|
| - EnumValueCondition.decorateEnumConstantName(constant) + ",\n");
|
| - }
|
| - builder.append("\t }\n");
|
| - addMember(enumName, builder);
|
| -
|
| - return BoxableType.createReference(new NamePath(enumName, getClassContextNamespace()));
|
| - }
|
| -
|
| - @Override
|
| - public BoxableType generateNestedObject(String description,
|
| - List<ObjectProperty> propertyList) throws IOException {
|
| - DeferredWriter builder = new DeferredWriter();
|
| -
|
| - if (description != null) {
|
| - builder.append("\t /**\n " + description + "\n */\n");
|
| - }
|
| -
|
| - String objectName = capitalizeFirstChar(getMemberName());
|
| -
|
| - if (propertyList == null) {
|
| - builder.append("\t @org.chromium.sdk.internal.protocolparser.JsonType(" +
|
| - "allowsOtherProperties=true)\n");
|
| - builder.append("\t public interface " + objectName +
|
| - " extends org.chromium.sdk.internal.protocolparser.JsonObjectBased {\n");
|
| - builder.append("\t }\n");
|
| - } else {
|
| - builder.append("\t @org.chromium.sdk.internal.protocolparser.JsonType\n");
|
| - builder.append("\t public interface " + objectName + " {\n");
|
| - for (ObjectProperty property : propertyList) {
|
| - if (property.description() != null) {
|
| - builder.append("\t /**\n " + property.description() + "\n */\n");
|
| - }
|
| -
|
| - String methodName = generateMethodNameSubstitute(property.name(), builder);
|
| -
|
| - MemberScope memberScope = newMemberScope(property.name());
|
| -
|
| - QualifiedTypeData propertyTypeData = memberScope.resolveType(property);
|
| -
|
| - propertyTypeData.writeAnnotations(builder, " ");
|
| -
|
| - builder.append("\t " +
|
| - propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + " " +
|
| - methodName + "();\n");
|
| - builder.append("\t\n");
|
| - }
|
| - builder.append("\t }\n");
|
| - }
|
| -
|
| - addMember(objectName, builder);
|
| -
|
| - jsonProtocolParserClassNames.add(getFullName() + "." + objectName);
|
| -
|
| - return BoxableType.createReference(new NamePath(objectName, getClassContextNamespace()));
|
| - }
|
| - }
|
| - }
|
| -
|
| - class OutputClassScope extends ClassScope {
|
| - OutputClassScope(NamePath classNamePath) {
|
| - super(classNamePath);
|
| - }
|
| -
|
| - <P> void generateCommandParamsBody(IndentWriter writer, List<P> parameters,
|
| - final PropertyLikeAccess<P> access, String commandName) throws IOException {
|
| -
|
| - // A helper type that represents either actual (logical) parameter or
|
| - // a helper has_ parameter for nullable-and-optional values.
|
| - abstract class ParamData {
|
| - final String name;
|
| - final String description;
|
| - ParamData(String name, String description) {
|
| - this.name = name;
|
| - this.description = description;
|
| - }
|
| - abstract String getJavaTypeText();
|
| - abstract void writeSetCode(IndentWriter writer);
|
| - }
|
| -
|
| - class LogicalParamData extends ParamData {
|
| - final QualifiedTypeData qualifiedTypeData;
|
| - final String logicalName;
|
| - LogicalParamData(String name, String description, QualifiedTypeData qualifiedTypeData,
|
| - String logicalName) {
|
| - super(name, description);
|
| - this.qualifiedTypeData = qualifiedTypeData;
|
| - this.logicalName = logicalName;
|
| - }
|
| - @Override String getJavaTypeText() {
|
| - return qualifiedTypeData.getJavaType().getShortText(getClassContextNamespace());
|
| - }
|
| - @Override
|
| - void writeSetCode(IndentWriter writer) {
|
| - writer.append("\t this.put(\"" + logicalName + "\", " + name + ");\n");
|
| - }
|
| - }
|
| -
|
| - class OptionalLogicalParamData extends LogicalParamData {
|
| - final String condition;
|
| - OptionalLogicalParamData(String name, String description,
|
| - QualifiedTypeData qualifiedTypeData, String logicalName,
|
| - String condition) {
|
| - super(name, description, qualifiedTypeData, logicalName);
|
| - this.condition = condition;
|
| - }
|
| - @Override
|
| - void writeSetCode(IndentWriter writer) {
|
| - writer.append("\t if (" + condition + ") {\n ");
|
| - super.writeSetCode(writer);
|
| - writer.append("\t }\n");
|
| - }
|
| - }
|
| -
|
| - // Resolve parameter types and generate helper parameters.
|
| - List<ParamData> physicalParameters;
|
| - if (parameters == null) {
|
| - physicalParameters = Collections.emptyList();
|
| - } else {
|
| - physicalParameters = new ArrayList<ParamData>(parameters.size());
|
| - for (final P param : parameters) {
|
| - String logicalName = access.getName(param);
|
| - String description = access.forTypedObject().getDescription(param);
|
| - ClassScope.MemberScope memberScope = newMemberScope(logicalName);
|
| - final QualifiedTypeData paramTypeData =
|
| - memberScope.resolveType(param, access.forTypedObject());
|
| - if (paramTypeData.isNullable() && paramTypeData.isOptional()) {
|
| - String paramName = logicalName;
|
| - final String helperParamName = "has" + capitalizeFirstChar(paramName);
|
| - ParamData mainParamData = new OptionalLogicalParamData(paramName, description,
|
| - paramTypeData, logicalName, helperParamName);
|
| - String helperDescription =
|
| - "whether '" + paramName + "' actually contains value (possibly null)";
|
| - ParamData helperParamData = new ParamData(helperParamName, helperDescription) {
|
| - @Override String getJavaTypeText() {
|
| - return "boolean";
|
| - }
|
| - @Override
|
| - void writeSetCode(IndentWriter writer) {
|
| - }
|
| - };
|
| - physicalParameters.add(helperParamData);
|
| - physicalParameters.add(mainParamData);
|
| - } else {
|
| - ParamData data;
|
| - if (paramTypeData.isOptional()) {
|
| - String paramName = logicalName + "Opt";
|
| - data = new OptionalLogicalParamData(paramName, description, paramTypeData,
|
| - logicalName, paramName + " != null");
|
| - } else {
|
| - data = new LogicalParamData(logicalName, description, paramTypeData, logicalName);
|
| - }
|
| - physicalParameters.add(data);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Generate code.
|
| - boolean hasDoc = false;
|
| - for (ParamData paramData : physicalParameters) {
|
| - if (paramData.description != null) {
|
| - hasDoc = true;
|
| - break;
|
| - }
|
| - }
|
| - if (hasDoc) {
|
| - writer.append("\t /**\n");
|
| - for (ParamData paramData : physicalParameters) {
|
| - if (paramData.description != null) {
|
| - writer.append("\t @param " + paramData.name + " " +
|
| - paramData.description + "\n");
|
| - }
|
| - }
|
| - writer.append("\t */\n");
|
| - }
|
| - writer.append("\t public " + getShortClassName() +"(");
|
| - {
|
| - boolean needComa = false;
|
| - for (ParamData paramData : physicalParameters) {
|
| - if (needComa) {
|
| - writer.append(", ");
|
| - }
|
| - writer.append(paramData.getJavaTypeText() + " " + paramData.name);
|
| - needComa = true;
|
| - }
|
| - }
|
| - writer.append(") {\n");
|
| - for (ParamData paramData : physicalParameters) {
|
| - paramData.writeSetCode(writer);
|
| - }
|
| - writer.append("\t }\n");
|
| - writer.append("\n");
|
| - }
|
| -
|
| - @Override
|
| - protected TypeData.Direction getTypeDirection() {
|
| - return TypeData.Direction.OUTPUT;
|
| - }
|
| -
|
| - @Override
|
| - protected MemberScope newMemberScope(String memberName) {
|
| - return new OutputMemberScope(memberName);
|
| - }
|
| -
|
| - class OutputMemberScope extends MemberScope {
|
| - protected OutputMemberScope(String memberName) {
|
| - super(memberName);
|
| - }
|
| -
|
| - @Override
|
| - public BoxableType generateEnum(String description, List<String> enumConstants) {
|
| - DeferredWriter builder = new DeferredWriter();
|
| - if (description != null) {
|
| - builder.append("\t /**\n " + description + "\n */\n");
|
| - }
|
| - String enumName = capitalizeFirstChar(getMemberName());
|
| - builder.append("\t public enum " + enumName +
|
| - " implements org.json.simple.JSONAware{\n");
|
| - for (String constant : enumConstants) {
|
| - builder.append("\t " + EnumValueCondition.decorateEnumConstantName(constant) +
|
| - "(\"" + constant + "\"),\n");
|
| - }
|
| - builder.append("\t ;\n");
|
| - builder.append("\t private final String protocolValue;\n");
|
| - builder.append("\t\n");
|
| - builder.append("\t " + enumName + "(String protocolValue) {\n");
|
| - builder.append("\t this.protocolValue = protocolValue;\n");
|
| - builder.append("\t }\n");
|
| - builder.append("\t\n");
|
| - builder.append("\t @Override public String toJSONString() {\n");
|
| - builder.append("\t return '\"' + protocolValue + '\"';\n");
|
| - builder.append("\t }\n");
|
| - builder.append("\t }\n");
|
| - addMember(enumName, builder);
|
| -
|
| - return BoxableType.createReference(new NamePath(enumName, getClassContextNamespace()));
|
| - }
|
| -
|
| - @Override
|
| - public BoxableType generateNestedObject(String description,
|
| - List<ObjectProperty> propertyList) throws IOException {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * An abstract code writer that supports indents. This approach is an attempt to build
|
| - * purely data-driven writer. In other versions similar interfaces usually had
|
| - * "new line" and "append" separate methods that have to be called in proper order.
|
| - * <p>
|
| - * Here "\t" symbol has a special treatment -- it denotes line start spaces in any
|
| - * fragment. The writer simply replaces it with a necessary number of spaces.
|
| - */
|
| - private interface IndentWriter {
|
| - void append(String text);
|
| -
|
| - IndentWriter createInner();
|
| -
|
| - String INDENT = " ";
|
| - }
|
| -
|
| - private static class DeferredWriter implements IndentWriter {
|
| - private final String indent;
|
| - private final StringBuilder builder;
|
| -
|
| - DeferredWriter() {
|
| - this("", new StringBuilder());
|
| - }
|
| -
|
| - DeferredWriter(String indent, StringBuilder builder) {
|
| - this.indent = indent;
|
| - this.builder = builder;
|
| - }
|
| -
|
| - @Override
|
| - public void append(String text) {
|
| - text = text.replaceAll("\t", "\t" + indent);
|
| - builder.append(text);
|
| - }
|
| -
|
| - @Override
|
| - public IndentWriter createInner() {
|
| - return new DeferredWriter(indent + INDENT, builder);
|
| - }
|
| -
|
| - void writeContent(IndentWriter output) {
|
| - output.append(builder.toString());
|
| - }
|
| - }
|
| -
|
| - private static class IndentWriterImpl implements IndentWriter {
|
| - private final String indent;
|
| - private final Appendable output;
|
| -
|
| - IndentWriterImpl(Appendable output, String indent) {
|
| - this.output = output;
|
| - this.indent = indent;
|
| - }
|
| -
|
| - @Override
|
| - public void append(String text) {
|
| - text = text.replaceAll("\t", indent);
|
| - try {
|
| - output.append(text);
|
| - } catch (IOException e) {
|
| - throw new RuntimeException(e);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public IndentWriter createInner() {
|
| - return new IndentWriterImpl(output, indent + INDENT);
|
| - }
|
| - }
|
| -
|
| - private interface ResolveAndGenerateScope {
|
| - String getDomainName();
|
| - TypeData.Direction getTypeDirection();
|
| -
|
| - <T> QualifiedTypeData resolveType(T typedObject, TypedObjectAccess<T> access);
|
| -
|
| - BoxableType generateEnum(String description, List<String> enumConstants);
|
| - BoxableType generateNestedObject(String description,
|
| - List<ObjectProperty> properties) throws IOException;
|
| - }
|
| -
|
| - <T> QualifiedTypeData resolveType(final T typedObject, final TypedObjectAccess<T> access,
|
| - final ResolveAndGenerateScope scope) {
|
| - UnqualifiedTypeData unqualifiedType =
|
| - switchByType(typedObject, access, new TypeVisitor<UnqualifiedTypeData>() {
|
| - @Override public UnqualifiedTypeData visitRef(String refName) {
|
| - BoxableType typeRef = resolveRefType(scope.getDomainName(), refName,
|
| - scope.getTypeDirection());
|
| - return new UnqualifiedTypeData(typeRef);
|
| - }
|
| - @Override public UnqualifiedTypeData visitBoolean() {
|
| - return UnqualifiedTypeData.BOOLEAN;
|
| - }
|
| -
|
| - @Override public UnqualifiedTypeData visitEnum(List<String> enumConstants) {
|
| - BoxableType enumName = scope.generateEnum(getDescription(), enumConstants);
|
| - return new UnqualifiedTypeData(enumName);
|
| - }
|
| -
|
| - @Override public UnqualifiedTypeData visitString() {
|
| - return UnqualifiedTypeData.STRING;
|
| - }
|
| - @Override public UnqualifiedTypeData visitInteger() {
|
| - return UnqualifiedTypeData.LONG;
|
| - }
|
| - @Override public UnqualifiedTypeData visitNumber() {
|
| - return UnqualifiedTypeData.NUMBER;
|
| - }
|
| - @Override public UnqualifiedTypeData visitArray(ArrayItemType items) {
|
| - QualifiedTypeData itemQualifiedType =
|
| - scope.resolveType(items, TypedObjectAccess.FOR_ARRAY_ITEM);
|
| - return new UnqualifiedTypeData(BoxableType.createList(itemQualifiedType.getJavaType()));
|
| - }
|
| - @Override public UnqualifiedTypeData visitObject(List<ObjectProperty> properties) {
|
| - BoxableType nestedObjectName;
|
| - try {
|
| - nestedObjectName = scope.generateNestedObject(getDescription(), properties);
|
| - } catch (IOException e) {
|
| - throw new RuntimeException(e);
|
| - }
|
| - return new UnqualifiedTypeData(nestedObjectName, false);
|
| - }
|
| - @Override public UnqualifiedTypeData visitUnknown() {
|
| - return UnqualifiedTypeData.ANY;
|
| - }
|
| - private <S> String getDescription() {
|
| - return access.getDescription(typedObject);
|
| - }
|
| - });
|
| -
|
| - return unqualifiedType.getQualifiedType(access.getOptional(typedObject) == Boolean.TRUE);
|
| - }
|
| -
|
| - private static class UnqualifiedTypeData {
|
| - private final BoxableType typeRef;
|
| - private final boolean nullable;
|
| -
|
| - UnqualifiedTypeData(BoxableType typeRef) {
|
| - this(typeRef, false);
|
| - }
|
| -
|
| - UnqualifiedTypeData(BoxableType typeRef, boolean nullable) {
|
| - this.typeRef = typeRef;
|
| - this.nullable = nullable;
|
| - }
|
| -
|
| - QualifiedTypeData getQualifiedType(boolean optional) {
|
| - BoxableType ref;
|
| - if (optional) {
|
| - ref = typeRef.convertToPureReference();
|
| - } else {
|
| - ref = typeRef;
|
| - }
|
| - return new QualifiedTypeData(ref, optional, nullable);
|
| - }
|
| -
|
| - static final UnqualifiedTypeData BOOLEAN = new UnqualifiedTypeData(BoxableType.BOOLEAN, false);
|
| - static final UnqualifiedTypeData STRING = new UnqualifiedTypeData(BoxableType.STRING, false);
|
| - static final UnqualifiedTypeData LONG = new UnqualifiedTypeData(BoxableType.LONG, false);
|
| - static final UnqualifiedTypeData NUMBER = new UnqualifiedTypeData(BoxableType.NUMBER, false);
|
| - static final UnqualifiedTypeData ANY = new UnqualifiedTypeData(BoxableType.OBJECT, true);
|
| - }
|
| -
|
| - private static class QualifiedTypeData {
|
| - private final BoxableType typeRef;
|
| - private final boolean optional;
|
| - private final boolean nullable;
|
| -
|
| - QualifiedTypeData(BoxableType typeRef, boolean optional, boolean nullable) {
|
| - this.typeRef = typeRef;
|
| - this.optional = optional;
|
| - this.nullable = nullable;
|
| - }
|
| -
|
| - boolean isOptional() {
|
| - return optional;
|
| - }
|
| - boolean isNullable() {
|
| - return nullable;
|
| - }
|
| - BoxableType getJavaType() {
|
| - return typeRef;
|
| - }
|
| -
|
| - void writeAnnotations(IndentWriter appendable, String indent) throws IOException {
|
| - if (isOptional()) {
|
| - appendable.append("\t" + indent +
|
| - "@org.chromium.sdk.internal.protocolparser.JsonOptionalField\n");
|
| - }
|
| - if (isNullable()) {
|
| - appendable.append("\t" + indent +
|
| - "@org.chromium.sdk.internal.protocolparser.JsonNullable\n");
|
| - }
|
| - }
|
| - }
|
| -
|
| - private void generateParserInterfaceList() throws IOException {
|
| - JavaFileUpdater fileUpdater =
|
| - startJavaFile(INPUT_PACKAGE, PARSER_INTERFACE_LIST_CLASS_NAME + ".java");
|
| -
|
| - // Write classes in stable order.
|
| - Collections.sort(jsonProtocolParserClassNames);
|
| -
|
| - Writer writer = fileUpdater.getWriter();
|
| -
|
| - writer.write("public class " + PARSER_INTERFACE_LIST_CLASS_NAME + " {\n");
|
| - writer.write(" public static final Class<?>[] LIST = {\n");
|
| - for (String name : jsonProtocolParserClassNames) {
|
| - writer.write(" " + name + ".class" + ",\n");
|
| - }
|
| - writer.write(" };\n");
|
| - writer.write("}\n");
|
| -
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - private void generateParserRoot(List<ParserRootInterfaceItem> parserRootInterfaceItems)
|
| - throws IOException {
|
| - JavaFileUpdater fileUpdater =
|
| - startJavaFile(INPUT_PACKAGE, PARSER_ROOT_INTERFACE_NAME + ".java");
|
| -
|
| - // Write classes in stable order.
|
| - Collections.sort(parserRootInterfaceItems);
|
| -
|
| - Writer writer = fileUpdater.getWriter();
|
| -
|
| - writer.write("@org.chromium.sdk.internal.protocolparser.JsonParserRoot\n");
|
| - writer.write("public interface " + PARSER_ROOT_INTERFACE_NAME + " {\n");
|
| - for (ParserRootInterfaceItem item : parserRootInterfaceItems) {
|
| - item.writeCode(writer);
|
| - }
|
| - writer.write("}\n");
|
| -
|
| - fileUpdater.update();
|
| - }
|
| -
|
| - private static abstract class BoxableType {
|
| - public static BoxableType create(String boxed, String unboxed) {
|
| - return new Base(boxed, unboxed);
|
| - }
|
| -
|
| - public static BoxableType createReference(NamePath namePath) {
|
| - return new Reference(namePath);
|
| - }
|
| -
|
| - public static BoxableType createList(BoxableType itemType) {
|
| - return new ListType(itemType.convertToPureReference());
|
| - }
|
| -
|
| - abstract String getFullText();
|
| -
|
| - abstract String getShortText(NamePath contextNamespace);
|
| -
|
| - abstract BoxableType convertToPureReference();
|
| -
|
| - private static class Base extends BoxableType {
|
| - private final NamePath boxed;
|
| - private final String unboxed;
|
| -
|
| - private Base(String boxed, String unboxed) {
|
| - this.boxed = new NamePath(boxed);
|
| - this.unboxed = unboxed;
|
| - }
|
| -
|
| - @Override String getFullText() {
|
| - return unboxed;
|
| - }
|
| -
|
| - @Override String getShortText(NamePath contextNamespace) {
|
| - return getFullText();
|
| - }
|
| -
|
| - @Override BoxableType convertToPureReference() {
|
| - return new Reference(boxed);
|
| - }
|
| - }
|
| -
|
| - private static class Reference extends BoxableType {
|
| - private final NamePath namePath;
|
| -
|
| - private Reference(NamePath namePath) {
|
| - this.namePath = namePath;
|
| - }
|
| -
|
| - String getFullText() {
|
| - return namePath.getFullText();
|
| - }
|
| -
|
| - String getShortText(NamePath contextNamespace) {
|
| - int nameLength = namePath.getLength();
|
| - int contextLength = contextNamespace.getLength();
|
| - if (nameLength > contextLength) {
|
| - StringBuilder builder = subtractContextRecursively(namePath, nameLength - contextLength,
|
| - contextNamespace);
|
| - if (builder != null) {
|
| - return builder.toString();
|
| - }
|
| - }
|
| - return namePath.getFullText();
|
| - }
|
| -
|
| - private StringBuilder subtractContextRecursively(NamePath namePos, int count,
|
| - NamePath prefix) {
|
| - if (count > 1) {
|
| - StringBuilder result =
|
| - subtractContextRecursively(namePos.getParent(), count - 1, prefix);
|
| - if (result == null) {
|
| - return null;
|
| - }
|
| - result.append('.');
|
| - result.append(namePos.getLastComponent());
|
| - return result;
|
| - } else {
|
| - String nameComponent = namePos.getLastComponent();
|
| - namePos = namePos.getParent();
|
| - do {
|
| - if (!namePos.getLastComponent().equals(prefix.getLastComponent())) {
|
| - return null;
|
| - }
|
| - namePos = namePos.getParent();
|
| - prefix = prefix.getParent();
|
| - } while (namePos != null);
|
| -
|
| - StringBuilder result = new StringBuilder();
|
| - result.append(nameComponent);
|
| - return result;
|
| - }
|
| - }
|
| -
|
| - BoxableType convertToPureReference() {
|
| - return this;
|
| - }
|
| - }
|
| -
|
| - private static class ListType extends BoxableType {
|
| - private final BoxableType itemType;
|
| -
|
| - public ListType(BoxableType itemType) {
|
| - this.itemType = itemType;
|
| - }
|
| -
|
| - @Override String getFullText() {
|
| - return "java.util.List<" + itemType.getFullText() + ">";
|
| - }
|
| -
|
| - @Override String getShortText(NamePath contextNamespace) {
|
| - return "java.util.List<" + itemType.getShortText(contextNamespace) + ">";
|
| - }
|
| -
|
| - @Override
|
| - BoxableType convertToPureReference() {
|
| - return this;
|
| - }
|
| - }
|
| -
|
| - static final BoxableType STRING = BoxableType.createReference(new NamePath("String"));
|
| - static final BoxableType OBJECT = BoxableType.createReference(new NamePath("Object"));
|
| - static final BoxableType NUMBER = BoxableType.createReference(new NamePath("Number"));
|
| - static final BoxableType LONG = BoxableType.create("Long", "long");
|
| - static final BoxableType BOOLEAN = BoxableType.create("Boolean", "boolean");
|
| - }
|
| -
|
| - private static class NamePath {
|
| - private final String lastComponent;
|
| - private final NamePath parent;
|
| -
|
| - NamePath(String component) {
|
| - this(component, null);
|
| - }
|
| -
|
| - NamePath(String component, NamePath parent) {
|
| - this.lastComponent = component;
|
| - this.parent = parent;
|
| - }
|
| -
|
| - NamePath getParent() {
|
| - return parent;
|
| - }
|
| -
|
| - String getLastComponent() {
|
| - return lastComponent;
|
| - }
|
| -
|
| - int getLength() {
|
| - int res = 1;
|
| - for (NamePath current = this; current != null; current = current.getParent()) {
|
| - res++;
|
| - }
|
| - return res;
|
| - }
|
| -
|
| - String getFullText() {
|
| - StringBuilder result = new StringBuilder();
|
| - fillFullPath(result);
|
| - return result.toString();
|
| - }
|
| -
|
| - private void fillFullPath(StringBuilder result) {
|
| - if (parent != null) {
|
| - parent.fillFullPath(result);
|
| - result.append('.');
|
| - }
|
| - result.append(lastComponent);
|
| - }
|
| - }
|
| -
|
| -
|
| -
|
| - private static class ParserRootInterfaceItem implements Comparable<ParserRootInterfaceItem> {
|
| - private final String domain;
|
| - private final String name;
|
| - private final ClassNameScheme.Input nameScheme;
|
| - private final String fullName;
|
| -
|
| - public ParserRootInterfaceItem(String domain, String name, ClassNameScheme.Input nameScheme) {
|
| - this.domain = domain;
|
| - this.name = name;
|
| - this.nameScheme = nameScheme;
|
| - fullName = nameScheme.getFullName(domain, name).getFullText();
|
| - }
|
| -
|
| - void writeCode(Writer writer) throws IOException {
|
| - writer.write(" @org.chromium.sdk.internal.protocolparser.JsonParseMethod\n");
|
| - writer.write(" " + fullName + " " + nameScheme.getParseMethodName(domain, name) +
|
| - "(org.json.simple.JSONObject obj)" +
|
| - " throws org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;\n");
|
| - writer.write("\n");
|
| - }
|
| -
|
| - @Override
|
| - public int compareTo(ParserRootInterfaceItem o) {
|
| - return this.fullName.compareTo(o.fullName);
|
| - }
|
| - }
|
| -
|
| - private abstract static class ClassNameScheme {
|
| - private final String suffix;
|
| -
|
| - ClassNameScheme(String suffix) {
|
| - this.suffix = suffix;
|
| - }
|
| -
|
| - NamePath getFullName(String domainName, String baseName) {
|
| - return new NamePath(getShortName(baseName), new NamePath(getPackageNameVirtual(domainName)));
|
| - }
|
| -
|
| - String getShortName(String baseName) {
|
| - return capitalizeFirstChar(baseName) + suffix;
|
| - }
|
| -
|
| - protected abstract String getPackageNameVirtual(String domainName);
|
| -
|
| - static class Input extends ClassNameScheme {
|
| - Input(String suffix) {
|
| - super(suffix);
|
| - }
|
| -
|
| - @Override protected String getPackageNameVirtual(String domainName) {
|
| - return getPackageName(domainName);
|
| - }
|
| -
|
| - String getParseMethodName(String domain, String name) {
|
| - return "parse" + capitalizeFirstChar(domain) + getShortName(name);
|
| - }
|
| -
|
| - static String getPackageName(String domainName) {
|
| - return INPUT_PACKAGE + "." + domainName.toLowerCase();
|
| - }
|
| - }
|
| -
|
| - static class Output extends ClassNameScheme {
|
| - Output(String suffix) {
|
| - super(suffix);
|
| - }
|
| -
|
| - @Override protected String getPackageNameVirtual(String domainName) {
|
| - return getPackageName(domainName);
|
| - }
|
| -
|
| - static String getPackageName(String domainName) {
|
| - return OUTPUT_PACKAGE + "." + domainName.toLowerCase();
|
| - }
|
| - }
|
| -
|
| - static class Common extends ClassNameScheme {
|
| - Common(String suffix) {
|
| - super(suffix);
|
| - }
|
| -
|
| - @Override protected String getPackageNameVirtual(String domainName) {
|
| - return getPackageName(domainName);
|
| - }
|
| -
|
| - static String getPackageName(String domainName) {
|
| - return COMMON_PACKAGE + "." + domainName.toLowerCase();
|
| - }
|
| - }
|
| - }
|
| -
|
| - interface Naming {
|
| - ClassNameScheme PARAMS = new ClassNameScheme.Output("Params");
|
| - ClassNameScheme ADDITIONAL_PARAM = new ClassNameScheme.Output("Param");
|
| - ClassNameScheme OUTPUT_TYPEDEF = new ClassNameScheme.Output("Typedef");
|
| -
|
| - ClassNameScheme.Input COMMAND_DATA = new ClassNameScheme.Input("Data");
|
| - ClassNameScheme.Input EVENT_DATA = new ClassNameScheme.Input("EventData");
|
| - ClassNameScheme INPUT_VALUE = new ClassNameScheme.Input("Value");
|
| - ClassNameScheme INPUT_ENUM = new ClassNameScheme.Input("Enum");
|
| - ClassNameScheme INPUT_TYPEDEF = new ClassNameScheme.Input("Typedef");
|
| -
|
| - ClassNameScheme COMMON_TYPEDEF = new ClassNameScheme.Common("Typedef");
|
| - }
|
| -
|
| - /**
|
| - * A set of external methods that provides a type-safe polymorphous access
|
| - * to several unrelated types.
|
| - */
|
| - private static abstract class TypedObjectAccess<T> {
|
| - abstract String getDescription(T obj);
|
| - abstract Boolean getOptional(T obj);
|
| - abstract String getRef(T obj);
|
| - abstract List<String> getEnum(T obj);
|
| - abstract String getType(T obj);
|
| - abstract ArrayItemType getItems(T obj);
|
| - abstract List<ObjectProperty> getProperties(T obj);
|
| -
|
| - static final TypedObjectAccess<Parameter> FOR_PARAMETER = new TypedObjectAccess<Parameter>() {
|
| - @Override String getDescription(Parameter obj) {
|
| - return obj.description();
|
| - }
|
| - @Override Boolean getOptional(Parameter obj) {
|
| - return obj.optional();
|
| - }
|
| - @Override String getRef(Parameter obj) {
|
| - return obj.ref();
|
| - }
|
| - @Override List<String> getEnum(Parameter obj) {
|
| - return obj.getEnum();
|
| - }
|
| - @Override String getType(Parameter obj) {
|
| - return obj.type();
|
| - }
|
| - @Override ArrayItemType getItems(Parameter obj) {
|
| - return obj.items();
|
| - }
|
| - @Override List<ObjectProperty> getProperties(Parameter obj) {
|
| - return obj.properties();
|
| - }
|
| - };
|
| -
|
| - static final TypedObjectAccess<ObjectProperty> FOR_OBJECT_PROPERTY =
|
| - new TypedObjectAccess<ObjectProperty>() {
|
| - @Override String getDescription(ObjectProperty obj) {
|
| - return obj.description();
|
| - }
|
| - @Override Boolean getOptional(ObjectProperty obj) {
|
| - return obj.optional();
|
| - }
|
| - @Override String getRef(ObjectProperty obj) {
|
| - return obj.ref();
|
| - }
|
| - @Override List<String> getEnum(ObjectProperty obj) {
|
| - return obj.getEnum();
|
| - }
|
| - @Override String getType(ObjectProperty obj) {
|
| - return obj.type();
|
| - }
|
| - @Override ArrayItemType getItems(ObjectProperty obj) {
|
| - return obj.items();
|
| - }
|
| - @Override List<ObjectProperty> getProperties(ObjectProperty obj) {
|
| - throw new RuntimeException();
|
| - }
|
| - };
|
| -
|
| - static final TypedObjectAccess<ArrayItemType> FOR_ARRAY_ITEM =
|
| - new TypedObjectAccess<ArrayItemType>() {
|
| - @Override String getDescription(ArrayItemType obj) {
|
| - return obj.description();
|
| - }
|
| - @Override Boolean getOptional(ArrayItemType obj) {
|
| - return obj.optional();
|
| - }
|
| - @Override String getRef(ArrayItemType obj) {
|
| - return obj.ref();
|
| - }
|
| - @Override List<String> getEnum(ArrayItemType obj) {
|
| - return obj.getEnum();
|
| - }
|
| - @Override String getType(ArrayItemType obj) {
|
| - return obj.type();
|
| - }
|
| - @Override ArrayItemType getItems(ArrayItemType obj) {
|
| - return obj.items();
|
| - }
|
| - @Override List<ObjectProperty> getProperties(ArrayItemType obj) {
|
| - return obj.properties();
|
| - }
|
| - };
|
| -
|
| - static final TypedObjectAccess<StandaloneType> FOR_STANDALONE =
|
| - new TypedObjectAccess<StandaloneType>() {
|
| - @Override String getDescription(StandaloneType obj) {
|
| - return obj.description();
|
| - }
|
| - @Override Boolean getOptional(StandaloneType obj) {
|
| - return null;
|
| - }
|
| - @Override String getRef(StandaloneType obj) {
|
| - return null;
|
| - }
|
| - @Override List<String> getEnum(StandaloneType obj) {
|
| - return obj.getEnum();
|
| - }
|
| - @Override String getType(StandaloneType obj) {
|
| - return obj.type();
|
| - }
|
| - @Override ArrayItemType getItems(StandaloneType obj) {
|
| - return obj.items();
|
| - }
|
| - @Override List<ObjectProperty> getProperties(StandaloneType obj) {
|
| - return obj.properties();
|
| - }
|
| - };
|
| - }
|
| -
|
| - /**
|
| - * A polymorphopus access to something like property (with name and type).
|
| - */
|
| - private static abstract class PropertyLikeAccess<T> {
|
| - abstract TypedObjectAccess<T> forTypedObject();
|
| - abstract String getName(T obj);
|
| -
|
| - static final PropertyLikeAccess<Parameter> PARAMETER = new PropertyLikeAccess<Parameter>() {
|
| - @Override TypedObjectAccess<Parameter> forTypedObject() {
|
| - return TypedObjectAccess.FOR_PARAMETER;
|
| - }
|
| - @Override String getName(Parameter obj) {
|
| - return obj.name();
|
| - }
|
| - };
|
| -
|
| - static final PropertyLikeAccess<ObjectProperty> PROPERTY =
|
| - new PropertyLikeAccess<ObjectProperty>() {
|
| - @Override TypedObjectAccess<ObjectProperty> forTypedObject() {
|
| - return TypedObjectAccess.FOR_OBJECT_PROPERTY;
|
| - }
|
| - @Override String getName(ObjectProperty obj) {
|
| - return obj.name();
|
| - }
|
| - };
|
| - }
|
| -
|
| - /**
|
| - * Resolve absolute (DOMAIN.TYPE) or relative (TYPE) typename.
|
| - */
|
| - private BoxableType resolveRefType(String scopeDomainName, String refName,
|
| - TypeData.Direction direction) {
|
| - int pos = refName.indexOf('.');
|
| - String domainName;
|
| - String shortName;
|
| - if (pos == -1) {
|
| - domainName = scopeDomainName;
|
| - shortName = refName;
|
| - } else {
|
| - domainName = refName.substring(0, pos);
|
| - shortName = refName.substring(pos + 1);
|
| - }
|
| - return typeMap.resolve(domainName, shortName, direction);
|
| - }
|
| -
|
| - private String generateMethodNameSubstitute(String originalName, IndentWriter output)
|
| - throws IOException {
|
| - if (!BAD_METHOD_NAMES.contains(originalName)) {
|
| - return originalName;
|
| - }
|
| - output.append("\t @org.chromium.sdk.internal.protocolparser.JsonField(jsonLiteralName=\"" +
|
| - originalName + "\")\n");
|
| - return "get" + Character.toUpperCase(originalName.charAt(0)) + originalName.substring(1);
|
| - }
|
| -
|
| - private static String capitalizeFirstChar(String str) {
|
| - if (Character.isLowerCase(str.charAt(0))) {
|
| - str = Character.toUpperCase(str.charAt(0)) + str.substring(1);
|
| - }
|
| - return str;
|
| - }
|
| -
|
| - private JavaFileUpdater startJavaFile(ClassNameScheme nameScheme, Domain domain,
|
| - String baseName) throws IOException {
|
| - String packageName = nameScheme.getPackageNameVirtual(domain.domain());
|
| - String fileName = nameScheme.getShortName(baseName) + ".java";
|
| - return startJavaFile(packageName, fileName);
|
| - }
|
| -
|
| - private JavaFileUpdater startJavaFile(String packageName, String filename) throws IOException {
|
| - String filePath = packageName.replace('.', '/');
|
| -
|
| - JavaFileUpdater fileUpdater = fileSet.createFileUpdater(filePath + "/" + filename);
|
| - Writer writer = fileUpdater.getWriter();
|
| - writer.write("// Generated source.\n");
|
| - writer.write("// Generator: " + this.getClass().getCanonicalName() + "\n");
|
| - writer.write("// Origin: " + originReference + "\n\n");
|
| - writer.write("package " + packageName + ";\n\n");
|
| - return fileUpdater;
|
| - }
|
| -
|
| - private interface TypeVisitor<R> {
|
| -
|
| - R visitRef(String refName);
|
| -
|
| - R visitBoolean();
|
| -
|
| - R visitEnum(List<String> enumConstants);
|
| -
|
| - R visitString();
|
| -
|
| - R visitInteger();
|
| -
|
| - R visitNumber();
|
| -
|
| - R visitArray(ArrayItemType items);
|
| -
|
| - R visitObject(List<ObjectProperty> properties);
|
| -
|
| - R visitUnknown();
|
| -
|
| - }
|
| -
|
| - private static <R, T> R switchByType(T typedObject, TypedObjectAccess<T> access,
|
| - TypeVisitor<R> visitor) {
|
| - String refName = access.getRef(typedObject);
|
| - if (refName != null) {
|
| - return visitor.visitRef(refName);
|
| - }
|
| - String typeName = access.getType(typedObject);
|
| - if (WipMetamodel.BOOLEAN_TYPE.equals(typeName)) {
|
| - return visitor.visitBoolean();
|
| - } else if (WipMetamodel.STRING_TYPE.equals(typeName)) {
|
| - if (access.getEnum(typedObject) != null) {
|
| - return visitor.visitEnum(access.getEnum(typedObject));
|
| - }
|
| - return visitor.visitString();
|
| - } else if (WipMetamodel.INTEGER_TYPE.equals(typeName)) {
|
| - return visitor.visitInteger();
|
| - } else if (WipMetamodel.NUMBER_TYPE.equals(typeName)) {
|
| - return visitor.visitNumber();
|
| - } else if (WipMetamodel.ARRAY_TYPE.equals(typeName)) {
|
| - return visitor.visitArray(access.getItems(typedObject));
|
| - } else if (WipMetamodel.OBJECT_TYPE.equals(typeName)) {
|
| - return visitor.visitObject(access.getProperties(typedObject));
|
| - } else if (WipMetamodel.ANY_TYPE.equals(typeName)) {
|
| - return visitor.visitUnknown();
|
| - } else if (WipMetamodel.UNKNOWN_TYPE.equals(typeName)) {
|
| - return visitor.visitUnknown();
|
| - }
|
| - throw new RuntimeException("Unrecognized type " + typeName);
|
| - }
|
| -
|
| - private static class TypeData {
|
| - private final String domain;
|
| - private final String name;
|
| -
|
| - private Input input = null;
|
| - private Output output = null;
|
| -
|
| - private StandaloneType type = null;
|
| - private StandaloneTypeBinding commonBinding = null;
|
| -
|
| - TypeData(String domain, String name) {
|
| - this.domain = domain;
|
| - this.name = name;
|
| - }
|
| -
|
| - void setType(StandaloneType type) {
|
| - this.type = type;
|
| - }
|
| -
|
| - Input getInput() {
|
| - if (input == null) {
|
| - input = new Input();
|
| - }
|
| - return input;
|
| - }
|
| -
|
| - Output getOutput() {
|
| - if (output == null) {
|
| - output = new Output();
|
| - }
|
| - return output;
|
| - }
|
| -
|
| - TypeRef get(Direction direction) {
|
| - return direction.get(this);
|
| - }
|
| -
|
| - void checkComplete() {
|
| - if (input != null) {
|
| - input.checkResolved();
|
| - }
|
| - if (output != null) {
|
| - output.checkResolved();
|
| - }
|
| - }
|
| -
|
| - enum Direction {
|
| - INPUT() {
|
| - @Override TypeRef get(TypeData typeData) {
|
| - return typeData.getInput();
|
| - }
|
| - },
|
| - OUTPUT() {
|
| - @Override TypeRef get(TypeData typeData) {
|
| - return typeData.getOutput();
|
| - }
|
| - };
|
| - abstract TypeRef get(TypeData typeData);
|
| - }
|
| -
|
| - abstract class TypeRef {
|
| - private StandaloneTypeBinding oneDirectionBinding = null;
|
| -
|
| - BoxableType resolve(TypeMap typeMap, DomainGenerator domainGenerator) {
|
| - if (commonBinding != null) {
|
| - return commonBinding.getJavaType();
|
| - }
|
| - if (oneDirectionBinding != null) {
|
| - return oneDirectionBinding.getJavaType();
|
| - }
|
| - StandaloneTypeBinding binding = resolveImpl(domainGenerator);
|
| - if (binding.getDirection() == null) {
|
| - commonBinding = binding;
|
| - } else {
|
| - oneDirectionBinding = binding;
|
| - }
|
| - typeMap.addTypeToGenerate(binding);
|
| - return binding.getJavaType();
|
| - }
|
| -
|
| - abstract StandaloneTypeBinding resolveImpl(DomainGenerator domainGenerator);
|
| -
|
| - void checkResolved() {
|
| - if (type == null) {
|
| - throw new RuntimeException();
|
| - }
|
| - }
|
| - }
|
| -
|
| - class Output extends TypeRef {
|
| - @Override
|
| - StandaloneTypeBinding resolveImpl(final DomainGenerator domainGenerator) {
|
| - if (type == null) {
|
| - throw new RuntimeException();
|
| - }
|
| - return domainGenerator.createStandaloneOutputTypeBinding(type, name);
|
| - }
|
| - }
|
| -
|
| - class Input extends TypeRef {
|
| - @Override
|
| - StandaloneTypeBinding resolveImpl(DomainGenerator domainGenerator) {
|
| - if (type == null) {
|
| - throw new RuntimeException();
|
| - }
|
| - return domainGenerator.createStandaloneInputTypeBinding(type);
|
| - }
|
| - }
|
| - }
|
| -
|
| - private interface StandaloneTypeBinding {
|
| - BoxableType getJavaType();
|
| - void generate() throws IOException;
|
| -
|
| - /** @return null if not direction-specific */
|
| - TypeData.Direction getDirection();
|
| -
|
| - interface Target {
|
| - BoxableType resolve(ResolveContext context);
|
| -
|
| - interface ResolveContext {
|
| - BoxableType generateNestedObject(String shortName, String description,
|
| - List<ObjectProperty> properties) throws IOException;
|
| - }
|
| - }
|
| -
|
| - class PredefinedTarget implements Target {
|
| - private final BoxableType resolvedType;
|
| -
|
| - PredefinedTarget(BoxableType resolvedType) {
|
| - this.resolvedType = resolvedType;
|
| - }
|
| -
|
| - @Override public BoxableType resolve(ResolveContext context) {
|
| - return resolvedType;
|
| - }
|
| -
|
| - public static final PredefinedTarget STRING = new PredefinedTarget(BoxableType.STRING);
|
| - public static final PredefinedTarget LONG = new PredefinedTarget(BoxableType.LONG);
|
| - public static final PredefinedTarget NUMBER = new PredefinedTarget(BoxableType.NUMBER);
|
| - }
|
| -
|
| - }
|
| -
|
| -
|
| - /**
|
| - * Keeps track of all referenced types.
|
| - * A type may be used and resolved (generated or hard-coded).
|
| - */
|
| - private static class TypeMap {
|
| - private final Map<List<String>, TypeData> map = new HashMap<List<String>, TypeData>();
|
| - private Map<String, DomainGenerator> domainGeneratorMap = null;
|
| - private List<StandaloneTypeBinding> typesToGenerate = new ArrayList<StandaloneTypeBinding>();
|
| -
|
| - void setDomainGeneratorMap(Map<String, DomainGenerator> domainGeneratorMap) {
|
| - this.domainGeneratorMap = domainGeneratorMap;
|
| - }
|
| -
|
| - BoxableType resolve(String domainName, String typeName,
|
| - TypeData.Direction direction) {
|
| - DomainGenerator domainGenerator = domainGeneratorMap.get(domainName);
|
| - if (domainGenerator == null) {
|
| - throw new RuntimeException("Failed to find domain generator: " + domainName);
|
| - }
|
| - return getTypeData(domainName, typeName).get(direction).resolve(this, domainGenerator);
|
| - }
|
| -
|
| - void addTypeToGenerate(StandaloneTypeBinding binding) {
|
| - typesToGenerate.add(binding);
|
| - }
|
| -
|
| - public void generateRequestedTypes() throws IOException {
|
| - // Size may grow during iteration.
|
| - for (int i = 0; i < typesToGenerate.size(); i++) {
|
| - typesToGenerate.get(i).generate();
|
| - }
|
| -
|
| - for (TypeData typeData : map.values()) {
|
| - typeData.checkComplete();
|
| - }
|
| - }
|
| -
|
| - TypeData getTypeData(String domainName, String typeName) {
|
| - List<String> key = createKey(domainName, typeName);
|
| - TypeData result = map.get(key);
|
| - if (result == null) {
|
| - result = new TypeData(domainName, typeName);
|
| - map.put(key, result);
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - private List<String> createKey(String domainName, String typeName) {
|
| - return Arrays.asList(domainName, typeName);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Records a list of files in the root directory and deletes files that were not re-generated.
|
| - */
|
| - private static class FileSet {
|
| - private final File rootDir;
|
| - private final Set<File> unusedFiles;
|
| -
|
| - FileSet(File rootDir) {
|
| - this.rootDir = rootDir;
|
| - List<File> files = new ArrayList<File>();
|
| - collectFilesRecursive(rootDir, files);
|
| - unusedFiles = new HashSet<File>(files);
|
| - }
|
| -
|
| - JavaFileUpdater createFileUpdater(String filePath) {
|
| - File file = new File(rootDir, filePath);
|
| - unusedFiles.remove(file);
|
| - return new JavaFileUpdater(file);
|
| - }
|
| -
|
| - void deleteOtherFiles() {
|
| - for (File file : unusedFiles) {
|
| - file.delete();
|
| - }
|
| - }
|
| -
|
| - private static void collectFilesRecursive(File file, Collection<File> list) {
|
| - if (file.isFile()) {
|
| - list.add(file);
|
| - } else if (file.isDirectory()) {
|
| - for (File inner : file.listFiles()) {
|
| - collectFilesRecursive(inner, list);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - private static final String[] DOMAIN_WHITE_LIST = {
|
| - "Debugger",
|
| - "Runtime",
|
| - "Page",
|
| - "Network",
|
| - "Console",
|
| - "DOM",
|
| - };
|
| -
|
| - private static void initializeKnownTypes(TypeMap typeMap) {
|
| - // Code example:
|
| - // typeMap.getTypeData("Page", "Cookie").getInput().setJavaTypeName("Object");
|
| - }
|
| -
|
| - private static final Set<String> BAD_METHOD_NAMES = new HashSet<String>(Arrays.asList(
|
| - "this"
|
| - ));
|
| -}
|
|
|