/*******************************************************************************
* Copyright (c) 2012 OpenLegacy Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* OpenLegacy Inc. - initial API and implementation
*******************************************************************************/
package org.openlegacy.designtime.terminal.generators.support;
import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openlegacy.EntityDefinition;
import org.openlegacy.definitions.ActionDefinition;
import org.openlegacy.definitions.support.SimpleActionDefinition;
import org.openlegacy.designtime.generators.CodeBasedScreenPartDefinition;
import org.openlegacy.designtime.generators.CodeBasedScreenTableDefinition;
import org.openlegacy.designtime.terminal.generators.ScreenPojoCodeModel;
import org.openlegacy.designtime.terminal.generators.support.DefaultScreenPojoCodeModel.Action;
import org.openlegacy.designtime.terminal.generators.support.DefaultScreenPojoCodeModel.Field;
import org.openlegacy.designtime.utils.JavaParserUtil;
import org.openlegacy.exceptions.EntityNotAccessibleException;
import org.openlegacy.terminal.definitions.ScreenEntityDefinition;
import org.openlegacy.terminal.definitions.ScreenFieldDefinition;
import org.openlegacy.terminal.definitions.SimpleScreenFieldDefinition;
import org.openlegacy.terminal.support.SimpleTerminalPosition;
import org.openlegacy.utils.StringUtil;
import japa.parser.JavaParser;
import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.body.BodyDeclaration;
import japa.parser.ast.body.ClassOrInterfaceDeclaration;
import japa.parser.ast.body.TypeDeclaration;
import japa.parser.ast.expr.AnnotationExpr;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class CodeBasedDefinitionUtils {
private final static Log logger = LogFactory.getLog(CodeBasedDefinitionUtils.class);
public static Map<String, ScreenFieldDefinition> getFieldsFromCodeModel(ScreenPojoCodeModel codeModel, String containerPrefix) {
// add prefix for field parts
containerPrefix = !StringUtil.isEmpty(containerPrefix) ? containerPrefix + "." : "";
Collection<Field> fields = codeModel.getFields();
Map<String, ScreenFieldDefinition> fieldDefinitions = new TreeMap<String, ScreenFieldDefinition>();
for (Field javaFieldModel : fields) {
if (!javaFieldModel.isScreenField()) {
continue;
}
SimpleScreenFieldDefinition fieldDefinition = new SimpleScreenFieldDefinition(containerPrefix
+ javaFieldModel.getName(), null);
fieldDefinition.setPosition(new SimpleTerminalPosition(javaFieldModel.getRow(), javaFieldModel.getColumn()));
fieldDefinition.setEditable(javaFieldModel.isEditable());
if (javaFieldModel.getLabelColumn() != null) {
fieldDefinition.setLabelPosition(new SimpleTerminalPosition(javaFieldModel.getRow(),
javaFieldModel.getLabelColumn()));
}
fieldDefinition.setDisplayName(StringUtil.stripQuotes(javaFieldModel.getDisplayName()));
if (javaFieldModel.getEndColumn() != null) {
fieldDefinition.setLength(javaFieldModel.getEndColumn() - javaFieldModel.getColumn() + 1);
}
fieldDefinition.setFieldTypeDefinition(javaFieldModel.getFieldTypeDefiniton());
fieldDefinition.setKey(javaFieldModel.isKey());
fieldDefinition.setHelpText(javaFieldModel.getHelpText());
fieldDefinitions.put(javaFieldModel.getName(), fieldDefinition);
}
return fieldDefinitions;
}
/**
*
* @param compilationUnit
* @param packageDir
* the package source folder. Used for finding related compilation units. May be null in test mode only
* @return
*/
public static ScreenEntityDefinition getEntityDefinition(CompilationUnit compilationUnit, File packageDir) {
List<TypeDeclaration> types = compilationUnit.getTypes();
CodeBasedScreenEntityDefinition screenDefinition = null;
TypeDeclaration type = compilationUnit.getTypes().get(0);
List<BodyDeclaration> members = type.getMembers();
for (BodyDeclaration bodyDeclaration : members) {
// look for inner classes
if (bodyDeclaration instanceof ClassOrInterfaceDeclaration) {
types.add((TypeDeclaration)bodyDeclaration);
}
}
for (TypeDeclaration typeDeclaration : types) {
List<AnnotationExpr> annotations = typeDeclaration.getAnnotations();
if (annotations == null) {
continue;
}
for (AnnotationExpr annotationExpr : annotations) {
ScreenPojoCodeModel screenEntityCodeModel = null;
if (JavaParserUtil.hasAnnotation(annotationExpr, AnnotationConstants.SCREEN_ENTITY_ANNOTATION)
|| JavaParserUtil.hasAnnotation(annotationExpr, AnnotationConstants.SCREEN_ENTITY_SUPER_CLASS_ANNOTATION)) {
screenEntityCodeModel = new DefaultScreenPojoCodeModel(compilationUnit,
(ClassOrInterfaceDeclaration)typeDeclaration, typeDeclaration.getName(), null);
screenDefinition = new CodeBasedScreenEntityDefinition(screenEntityCodeModel, packageDir);
}
if (JavaParserUtil.hasAnnotation(annotationExpr, AnnotationConstants.SCREEN_PART_ANNOTATION)) {
screenEntityCodeModel = new DefaultScreenPojoCodeModel(compilationUnit,
(ClassOrInterfaceDeclaration)typeDeclaration, typeDeclaration.getName(), null);
CodeBasedScreenPartDefinition partDefinition = new CodeBasedScreenPartDefinition(screenEntityCodeModel);
screenDefinition.getPartsDefinitions().put(partDefinition.getPartName(), partDefinition);
}
if (JavaParserUtil.hasAnnotation(annotationExpr, AnnotationConstants.SCREEN_TABLE_ANNOTATION)) {
screenEntityCodeModel = new DefaultScreenPojoCodeModel(compilationUnit,
(ClassOrInterfaceDeclaration)typeDeclaration, typeDeclaration.getName(), null);
CodeBasedScreenTableDefinition tableDefinition = new CodeBasedScreenTableDefinition(screenEntityCodeModel);
// concat "s" for table field name: Item class -> "items" field name
screenDefinition.getTableDefinitions().put(tableDefinition.getTableEntityName() + "s", tableDefinition);
}
}
}
return screenDefinition;
}
public static List<ActionDefinition> getActionsFromCodeModel(ScreenPojoCodeModel codeModel) {
List<Action> actions = codeModel.getActions();
List<ActionDefinition> actionDefinitions = new ArrayList<ActionDefinition>();
for (Action action : actions) {
String actionName = StringUtil.toClassName(action.getActionName());
SimpleActionDefinition actionDefinition = new SimpleActionDefinition(actionName,
StringUtil.stripQuotes(action.getDisplayName()));
if (action.getAlias() != null) {
actionDefinition.setAlias(StringUtil.stripQuotes(action.getAlias()));
}
actionDefinitions.add(actionDefinition);
}
return actionDefinitions;
}
public static List<EntityDefinition<?>> getChildScreensDefinitions(ScreenPojoCodeModel codeModel, File packageDir) {
List<EntityDefinition<?>> childDefinitions = new ArrayList<EntityDefinition<?>>();
if (packageDir == null) {
logger.warn(MessageFormat.format("Package directory for {0} is not defined. Unable to determine child screens",
codeModel.getClassName()));
return childDefinitions;
}
Collection<Field> fields = codeModel.getFields();
for (Field field : fields) {
if (!field.isChildScreenEntityField()) {
continue;
}
File childSourceFile = new File(packageDir, field.getType() + ".java");
if (!childSourceFile.exists()) {
logger.debug(MessageFormat.format("Source file for field {0} is not defined. Unable to find file {1}",
field.getName(), childSourceFile.getAbsoluteFile()));
continue;
}
try {
CompilationUnit compilationUnit = JavaParser.parse(childSourceFile);
ScreenEntityDefinition childEntityDefinition = getEntityDefinition(compilationUnit, packageDir);
if (childEntityDefinition.isChild()) {
childDefinitions.add(childEntityDefinition);
} else {
logger.warn(MessageFormat.format(
"A non child screen {0} is related from {1}. NOT added to it''s child screen list",
childEntityDefinition.getEntityClassName(), codeModel.getClassName()));
}
} catch (ParseException e) {
logger.warn("Failed parsing java file:" + e.getMessage());
} catch (IOException e) {
throw (new EntityNotAccessibleException(e));
}
}
return childDefinitions;
}
public static Set<EntityDefinition<?>> getAllChildScreensDefinitions(ScreenPojoCodeModel codeModel, File packageDir) {
@SuppressWarnings("unchecked")
Set<EntityDefinition<?>> childs = new ListOrderedSet();
childs.addAll(getChildScreensDefinitions(codeModel, packageDir));
for (EntityDefinition<?> childScreenDefinition : childs) {
Set<EntityDefinition<?>> childScreensDefinitions = childScreenDefinition.getAllChildEntitiesDefinitions();
if (childScreensDefinitions.size() > 0) {
logger.info(MessageFormat.format("Adding child screens to list all child screens. Adding: {0}",
childScreensDefinitions));
childs.addAll(childScreensDefinitions);
}
}
return childs;
}
}