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

import com.speedment.common.codegen.constant.DefaultType;
import com.speedment.common.codegen.constant.SimpleParameterizedType;
import com.speedment.common.codegen.model.Class;
import com.speedment.common.codegen.model.*;
import com.speedment.generator.translator.AbstractEntityAndManagerTranslator;
import com.speedment.runtime.config.Table;
import com.speedment.runtime.config.identifier.TableIdentifier;
import com.speedment.runtime.config.trait.HasColumn;
import com.speedment.runtime.config.trait.HasEnabled;
import com.speedment.runtime.core.manager.AbstractManager;
import com.speedment.runtime.core.manager.AbstractViewManager;

import java.util.Optional;
import java.util.stream.Stream;

import static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;
import static com.speedment.generator.standard.internal.util.GenerateMethodBodyUtil.generateFields;
import com.speedment.runtime.config.Column;
import com.speedment.runtime.config.PrimaryKeyColumn;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.joining;

/**
 *
 * @author Emil Forslund
 * @since 2.3.0
 */
public final class GeneratedManagerImplTranslator
    extends AbstractEntityAndManagerTranslator<Class> {

    public final static String FIELDS_METHOD = "fields",
        PRIMARY_KEYS_FIELDS_METHOD = "primaryKeyFields";

    public GeneratedManagerImplTranslator(Table table) {
        super(table, Class::of);
    }

    @Override
    protected Class makeCodeGenModel(File file) {

        return newBuilder(file, getSupport().generatedManagerImplName())
            ////////////////////////////////////////////////////////////////////
            // The table specific methods.                                    //
            ////////////////////////////////////////////////////////////////////
            .forEveryTable((clazz, table) -> {
                file.add(Import.of(getSupport().managerType()));

                clazz
                    .public_()
                    .abstract_()
                    .setSupertype(SimpleParameterizedType.create(
                        table.isView()
                        ? AbstractViewManager.class
                        : AbstractManager.class,
                        getSupport().entityType()
                    ))
                    .add(getSupport().generatedManagerType())
                    .add(Field.of("tableIdentifier", SimpleParameterizedType.create(TableIdentifier.class, getSupport().entityType())).private_().final_())
                    .add(Constructor.of().protected_()
                        .add("this.tableIdentifier = " + TableIdentifier.class.getSimpleName() + ".of("
                            + Stream.of(getSupport().dbmsOrThrow().getId(), getSupport().schemaOrThrow().getId(), getSupport().tableOrThrow().getId())
                                .map(s -> "\"" + s + "\"").collect(joining(", "))
                            + ");")
                    )
                    .add(Method.of("getTableIdentifier", SimpleParameterizedType.create(TableIdentifier.class, getSupport().entityType()))
                        .public_().add(OVERRIDE)
                        .add("return tableIdentifier;")
                    )
                    .add(
                        Method.of(FIELDS_METHOD,
                            DefaultType.stream(
                                SimpleParameterizedType.create(
                                    com.speedment.runtime.field.Field.class,
                                    getSupport().entityType()
                                )
                            )
                        )
                            .public_().add(OVERRIDE)
                            .add("return " + getSupport().managerName() + ".FIELDS.stream();")
                    )
                    .add(generateFields(getSupport(), file, PRIMARY_KEYS_FIELDS_METHOD,
                        () -> table.primaryKeyColumns()
                            .sorted(comparing(PrimaryKeyColumn::getOrdinalPosition))
                            .filter(HasEnabled::test)
                            .map(HasColumn::findColumn)
                            .filter(Optional::isPresent)
                            .map(Optional::get)
                    ));
            })
            .build();
    }

    @Override
    protected String getJavadocRepresentText() {
        return "The generated base implementation for the manager of every {@link "
            + getSupport().entityType().getTypeName() + "} entity.";
    }

    @Override
    protected String getClassOrInterfaceName() {
        return getSupport().generatedManagerImplName();
    }

    @Override
    public boolean isInGeneratedPackage() {
        return true;
    }
}

@@ -670,24 +670,307 @@
 d.manager;%0A%0A
+import static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;%0Aimport static com.speedment.generator.standard.internal.util.GenerateMethodBodyUtil.generateFields;%0Aimport static java.util.Comparator.comparing;%0Aimport static java.util.stream.Collectors.joining;%0A%0A
 import com.s
@@ -1176,17 +1176,224 @@
 n.model.
-*
+Constructor;%0Aimport com.speedment.common.codegen.model.Field;%0Aimport com.speedment.common.codegen.model.File;%0Aimport com.speedment.common.codegen.model.Import;%0Aimport com.speedment.common.codegen.model.Method
 ;%0Aimport
@@ -1460,24 +1460,78 @@
 Translator;%0A
+import com.speedment.runtime.config.PrimaryKeyColumn;%0A
 import com.s
@@ -1919,389 +1919,8 @@
 m;%0A%0A
-import static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;%0Aimport static com.speedment.generator.standard.internal.util.GenerateMethodBodyUtil.generateFields;%0Aimport com.speedment.runtime.config.Column;%0Aimport com.speedment.runtime.config.PrimaryKeyColumn;%0Aimport static java.util.Comparator.comparing;%0Aimport static java.util.stream.Collectors.joining;%0A%0A
 /**%0A
@@ -2083,27 +2083,22 @@
    p
-ublic final
+rivate
  static 
 Stri
@@ -2093,16 +2093,22 @@
  static 
+final 
 String F
@@ -2130,25 +2130,49 @@
 %22fields%22
-,
+;
 %0A    
-   
+private static final String
  PRIMARY
@@ -2803,16 +2803,84 @@
 ype()));
+%0A                file.add(Import.of(getSupport().entityImplType()));
 %0A%0A      
@@ -3898,32 +3898,291 @@
               )%0A
+                    .add(Method.of(%22create%22, SimpleParameterizedType.create(getSupport().entityType()))%0A                        .public_().add(OVERRIDE)%0A                        .add(%22return new %22 + getSupport().entityImplName() + %22();%22)%0A                    )%0A
                 

Include Manager#create() method in generator