All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.eugene.java.JavaGeneratorUtil Maven / Gradle / Ivy

/*
 * #%L
 * EUGene :: EUGene
 * 
 * $Id: JavaGeneratorUtil.java 1380 2014-06-19 06:47:21Z tchemit $
 * $HeadURL: https://svn.nuiton.org/eugene/tags/eugene-2.11/eugene/src/main/java/org/nuiton/eugene/java/JavaGeneratorUtil.java $
 * %%
 * Copyright (C) 2004 - 2010 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nuiton.eugene.java;

import org.apache.commons.lang3.StringUtils;
import org.nuiton.eugene.EugeneStereoTypes;
import org.nuiton.eugene.EugeneTagValues;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelClassifier;
import org.nuiton.eugene.models.object.ObjectModelElement;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelParameter;
import org.nuiton.util.StringUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * Utility class for pure java templates.
 *
 * @author tchemit 
 * @since 2.0.2
 */
public class JavaGeneratorUtil extends GeneratorUtil {

    public static final String OPERATION_GETTER_DEFAULT_PREFIX = "get";

    public static final String OPERATION_GETTER_BOOLEAN_PREFIX = "is";

    /**
     * dependency to add constants in interfaces via an enumeration.
     * 

* The literals of enumeration will be the value, and constant names will * be generated by transformers. * * @since 2.0.2 */ public static final String DEPENDENCIES_CONSTANTS = "constants"; /** * Duplicates in the {@code target} classifier the given {@code operations} * using a {@code transformer} to modify model. * * @param transformer the transformer to use * @param operations operations to duplicate * @param target where to duplicate operations * @param useVisibility flag to use operation visibilty to compute his * modifiers * @param extraModifiers scopes to apply to all operations */ public static void cloneOperations(ObjectModelTransformerToJava transformer, Iterable operations, ObjectModelClassifier target, boolean useVisibility, ObjectModelModifier... extraModifiers) { for (ObjectModelOperation op : operations) { ObjectModelOperation resultOp; ObjectModelModifier[] modifiers; if (useVisibility) { // compute visibility modifer String visibility = op.getVisibility(); ObjectModelModifier modifier = ObjectModelJavaModifier.fromVisibility(visibility); int length = extraModifiers.length; if (length == 0) { modifiers = new ObjectModelModifier[]{modifier}; } else { modifiers = new ObjectModelModifier[length + 1]; modifiers[0] = modifier; System.arraycopy(extraModifiers, 0, modifiers, 1, length); } } else { // just use the incoming modifiers modifiers = extraModifiers; } resultOp = transformer.addOperation(target, op.getName(), op.getReturnType(), modifiers ); for (ObjectModelParameter param : op.getParameters()) { transformer.addParameter(resultOp, param.getType(), param.getName() ); } for (String exception : op.getExceptions()) { transformer.addException(resultOp, exception); } } } /** * Check if the given classifier has the * {@link EugeneStereoTypes#STEREOTYPE_SKIP} stereotype. * * @param classifier classifier to test * @return {@code true} if stereotype was found, {@code false otherwise} * @see EugeneStereoTypes#STEREOTYPE_SKIP * @since 2.5 * @deprecated since 2.9, use now {@link EugeneStereoTypes#hasSkipStereotype(ObjectModelClassifier)} */ @Deprecated public static boolean hasSkipStereotype(ObjectModelClassifier classifier) { return EugeneStereoTypes.hasSkipStereotype(classifier); } /** * Cherche et renvoie le prefixe i18n à utiliser sur cet element, sinon sur * le model. * * @param element l'élément à tester * @param model le modele utilisé * @return le prefix i18n ou null si non spécifié * @since 2.3 * @deprecated since 2.9, use now {@link EugeneTagValues#getI18nPrefixTagValue(ObjectModelElement, ObjectModel)} */ @Deprecated public static String getI18nPrefixTagValue(ObjectModelElement element, ObjectModel model) { return EUGENE_TAG_VALUES.getI18nPrefixTagValue(element, model); } /** * Obtain the value of the {@link EugeneTagValues#TAG_DO_NOT_GENERATE_BOOLEAN_GET_METHODS} * tag value on the given model or classifier. *

* It will first look on the model, and then in the given classifier. * * @param model model to seek * @param classifier classifier to seek * @return the none empty value of the found tag value or {@code null} if not found nor empty. * @see EugeneTagValues#TAG_DO_NOT_GENERATE_BOOLEAN_GET_METHODS * @since 2.4.1 * @deprecated since 2.9, use now {@link EugeneTagValues#isDoNotGenerateBooleanGetMethods(ObjectModelClassifier, ObjectModel)} */ @Deprecated public static boolean isDoNotGenerateBooleanGetMethods(ObjectModel model, ObjectModelClassifier classifier) { boolean value = EUGENE_TAG_VALUES.isDoNotGenerateBooleanGetMethods(classifier, model); return value; } /** * Obtain the value of the {@link EugeneTagValues#TAG_CONSTANT_PREFIX} * tag value on the given model or classifier. *

* It will first look on the model, and then in the given classifier. * * @param model model to seek * @param classifier classifier to seek * @return the none empty value of the found tag value or {@code null} if not found nor empty. * @see EugeneTagValues#TAG_CONSTANT_PREFIX * @since 2.3 * @deprecated since 2.9, use now {@link EugeneTagValues#getConstantPrefixTagValue(ObjectModelClassifier, ObjectModel)} */ @Deprecated public static String getConstantPrefixTagValue(ObjectModel model, ObjectModelClassifier classifier) { String value = EUGENE_TAG_VALUES.getConstantPrefixTagValue(classifier, model); return value; } /** * Convertit une propriété javaBean son suffix utilisé pour écrire les * getter/setter correspondant. * * @param propertyName le nom de propriété a convertir * @return le nom capitalizé de la propriété JavaBean * @since 2.4.2 */ public static String capitalizeJavaBeanPropertyName(String propertyName) { if (StringUtils.isEmpty(propertyName)) { return propertyName; } if (propertyName.length() == 1) { // simple case : return propertyName.toUpperCase(); } // check if second caracter is up char c = propertyName.charAt(1); boolean carIsUp = Character.isUpperCase(c); if (carIsUp) { // this is a special and strange case : must not capitalize first char return propertyName; } return StringUtils.capitalize(propertyName); } /** * Split the given fqn which contains a generic declaration into his parts. *

* Example : *

     * java.util.List<Integer> : [java.util.List, Integer]
     * java.util.List<java.util.List<Integer>> : [java.util.List, java.util.List<Integer>]
     * java.util.Map<Integer, Integer> : [java.util.Map, Integer, Integer]
     * java.util.Map<Integer, java.util.List<Integer>> : [java.util.Map, Integer, java.util.List<Integer>]
     * 

*

* Note: We only deal with one level of generics here in * order to be able easly to rebuild after all the fqn with simple names... * * @param fqn the fqn to split * @return the array of all parts of the fqn. * @since 2.3.2 */ public static String[] splitGeneric(String fqn) { if (fqn == null) { return null; } int firstPartIndex = fqn.indexOf('<'); if (firstPartIndex == -1) { // no generics, just return the fqn return new String[]{fqn}; } List parts = new ArrayList(); parts.add(fqn.substring(0, firstPartIndex)); String rest = fqn.substring(firstPartIndex + 1, fqn.lastIndexOf('>')); if (containsGenerics(rest) && rest.contains(",")) { // there is others generics in generics, worse case... int begin = 0; int count = 0; int max = rest.length(); for (int i = 0; i < max; i++) { char c = rest.charAt(i); if (c == '<') { count++; } else if (c == '>') { count--; } else if (c == ',') { // arrives on a possible split if (count == 0) { // can safely add this part String part = rest.substring(begin, i); parts.add(part.trim()); begin = i + 1; } } } // there is a last part to add ? if (begin < max) { String part = rest.substring(begin, max); parts.add(part.trim()); } } else { // simple case : each part of the generics has no other generics String[] split = rest.split(","); for (String part : split) { parts.add(part.trim()); } } return parts.toArray(new String[parts.size()]); } /** * Join generics parts of a fqn into aparts. *

* Example : *

     * [java.util.List, Integer] : java.util.List<Integer>
     * [java.util.List, java.util.List<Integer>] : java.util.List<java.util.List<Integer>>
     * [java.util.Map, Integer, Integer] : java.util.Map<Integer, Integer>
     * [java.util.Map, Integer, java.util.List<Integer>] : java.util.Map<Integer, java.util.List<Integer>>
     * 
* * @param genericParts the parts of fqn * @return the fqn from his parts * @since 2.3.2 */ public static String joinGeneric(String... genericParts) { if (genericParts == null || genericParts.length == 0) { // this case should never happen ? return null; } if (genericParts.length == 1) { // in fact, no generics return genericParts[0]; } StringBuilder sb = new StringBuilder(genericParts[0]); sb.append("<").append(genericParts[1]); for (int i = 2, max = genericParts.length; i < max; i++) { String genericPart = genericParts[i]; sb.append(", ").append(genericPart); } sb.append('>'); return sb.toString(); } /** * Tells if the given fqn contains a generic declaration (says contains a * {@code <} caracter). * * @param fqn the fqn to test * @return {@code true} if given fqn contains a generic declaration * @since 2.3.2 */ public static boolean containsGenerics(String fqn) { return fqn.contains("<"); } /** * Split the given fqns gieven the list separator. *

* Example : *

     * Boolean, File : [Boolean, File]
     * Boolean , java.util.List<Integer> : [Boolean, java.util.List<Integer>]
     * 

*

*

* Note: You can NOT use as separator {@code '<'} nor * {@code '>'} nor {@code ' '}. * * @param fqns the fqn list to split * @param separator the fqn separactor char * @return the array of all parts of the fqn. * @since 2.3.2 */ public static String[] splitFqnList(String fqns, char separator) { if (separator == '<' || separator == '>' || separator == ' ') { throw new IllegalArgumentException( "Can not use '<' nor '>' for the separator"); } if (fqns == null) { return null; } List parts = new ArrayList(); // there is others generics in generics, worse case... int begin = 0; int count = 0; int max = fqns.length(); for (int i = 0; i < max; i++) { char c = fqns.charAt(i); if (c == '<') { count++; } else if (c == '>') { count--; } else if (c == separator) { // arrives on a possible split if (count == 0) { // can safely add this part String part = fqns.substring(begin, i); parts.add(part.trim()); begin = i + 1; } } } // there is a last part to add ? if (begin < max) { String part = fqns.substring(begin, max); parts.add(part.trim()); } return parts.toArray(new String[parts.size()]); } public static boolean isOrdered(ObjectModelAttribute attr) { return attr.isOrdered() || EugeneStereoTypes.hasOrderedStereotype(attr) || EugeneStereoTypes.hasIndexedStereotype(attr); } public static Class getCollectionType(ObjectModelAttribute attr) { boolean ordered = isOrdered(attr); boolean unique = EugeneStereoTypes.hasUniqueStereotype(attr); // Change type for Multiple attribute Class result; if (ordered) { if (unique) { result = LinkedHashSet.class; } else { result = List.class; } } else { if (unique) { result = Set.class; } else { result = Collection.class; } } return result; } public static Class getCollectionInstanceType(ObjectModelAttribute attr) { boolean ordered = isOrdered(attr); boolean unique = EugeneStereoTypes.hasUniqueStereotype(attr); // Change type for Multiple attribute Class result; if (ordered) { if (unique) { result = LinkedHashSet.class; } else { result = LinkedList.class; } } else { if (unique) { result = HashSet.class; } else { result = LinkedList.class; } } return result; } /** * Used to return the {@code operation} parameters for its declaration : * type and name of each parameter will be join as a string separated by a * comma. Usefull for operation parameters declaration in templates writing. * * @param operation to treate * @return the string corresponding to the list of operation parameters * for declaration syntax. */ public static String getOperationParametersListDeclaration( ObjectModelOperation operation) { String result = StringUtil.join( operation.getParameters(), OBJECT_MODEL_PARAMETER_TO_STRING_TYPE, ", ", false); return result; } /** * ToString contract for ObjectModelParameter with type and name. This * contract is used in * {@link StringUtil#join(Iterable, org.nuiton.util.StringUtil.ToString, String, boolean)} */ static final StringUtil.ToString OBJECT_MODEL_PARAMETER_TO_STRING_TYPE = new StringUtil.ToString() { @Override public String toString(ObjectModelParameter param) { return new StringBuilder(getAttributeInterfaceType(param)). append(' '). append(param.getName()). toString(); } }; /** * @param clazz the class where to look at * @return sous forme de String la liste des déclarations des attributes d'une classe donnée */ public static String getClassAttributesListDeclaration( ObjectModelClass clazz) { StringBuilder result = new StringBuilder(); Collection params = clazz.getAttributes(); for (Iterator j = params.iterator(); j.hasNext(); ) { ObjectModelAttribute attr = j.next(); result.append(getAttributeInterfaceType(attr, true)).append(" ").append(attr.getName()); if (j.hasNext()) { result.append(", "); } } return result.toString(); } /** * @param attribute the attribute to test * @return the type of the given attribute * @see #getAttributeInterfaceType(ObjectModelParameter, boolean) */ public static String getAttributeInterfaceType(ObjectModelParameter attribute) { return getAttributeInterfaceType(attribute, false); } /** * Retourne le type de l'attribut, c-a-d une List ou une collection * ou le type defini si la cardinalité n'est pas multiple * * @param attribute the attribute to test * @param useGenerics {@code true} if the attribute use a generic type * @return attribute type */ public static String getAttributeInterfaceType(ObjectModelParameter attribute, boolean useGenerics) { return getAttributeInterfaceType(attribute, attribute.getType(), useGenerics); } /** * Retourne le type de l'attribut, c-a-d une List ou une collection * ou le type defini si la cardinalité n'est pas multiple * * @param attribute the attribute to test * @param attributeType the attribute type * @param useGenerics {@code true} if the attribute use a generic type * @return attribute type */ public static String getAttributeInterfaceType(ObjectModelParameter attribute, String attributeType, boolean useGenerics) { String result; if (attribute instanceof ObjectModelAttribute && isNMultiplicity((ObjectModelAttribute) attribute)) { result = getCollectionType((ObjectModelAttribute) attribute).getName(); if (useGenerics) { result += "<" + attributeType + ">"; } } else { result = attributeType; } return result; } public static String getAttributeImplementationType(ObjectModelParameter attribute, String attributeType, boolean useGenerics) { String result; if (attribute instanceof ObjectModelAttribute && isNMultiplicity((ObjectModelAttribute) attribute)) { result = getCollectionInstanceType((ObjectModelAttribute) attribute).getName(); if (useGenerics) { result += "<" + attributeType + ">"; } } else { result = attributeType; } return result; } public static String getAttributeImplementationType(ObjectModelParameter attribute, boolean useGenerics) { return getAttributeImplementationType(attribute, attribute.getType(), useGenerics); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy