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

io.openmanufacturing.sds.aspectmodel.java.ImportTracker Maven / Gradle / Ivy

/*
 * Copyright (c) 2021 Robert Bosch Manufacturing Solutions GmbH
 *
 * See the AUTHORS file(s) distributed with this work for additional
 * information regarding authorship. 
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package io.openmanufacturing.sds.aspectmodel.java;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import io.openmanufacturing.sds.metamodel.Property;

/**
 * Tracks necessary Java imports during type resolution so that code generators can apply this information in order
 * to avoid statically bulk-importing all classes one might need.
 *
 * Code generators should use {@link #getUsedImportsWithoutJavaLang()} to generate a final list of imports.
 */
public class ImportTracker {
   private static final String GENERICS_START = "<";

   private static final String TYPE_BRACKETS_AND_WHITESPACE = "[<>\\s]";

   private final Set usedImports = new HashSet<>();
   private final Set usedStaticImports = new HashSet<>();

   /**
    * Resolves and tracks data type of the given meta model property.
    *
    * @param metaProperty the meta model property to resolve the data type for
    * @return the fully qualified class name (potentially including type parameters) of the resolved data type
    */
   public String getPropertyType( final Property metaProperty ) {
      final String propertyType = AspectModelJavaUtil
            .determinePropertyType( metaProperty.getCharacteristic(), false, this );
      trackPotentiallyParameterizedType( propertyType );
      if ( metaProperty.isOptional() ) {
         return AspectModelJavaUtil.containerType( Optional.class, propertyType, Optional.empty() );
      }
      return propertyType;
   }

   /**
    * Extracts and tracks the container type without any type parameters.
    *
    * @param parameterizedContainerType the fully qualified class name including type parameters
    * @return the raw container type
    */
   public String getRawContainerType( final String parameterizedContainerType ) {
      trackPotentiallyParameterizedType( parameterizedContainerType );
      return parameterizedContainerType.substring( 0, parameterizedContainerType.indexOf( GENERICS_START ) );
   }

   private void trackPotentiallyParameterizedType( final String potentiallyParameterizedType ) {
      if ( potentiallyParameterizedType.contains( GENERICS_START ) ) {
         final String rawContainerType = potentiallyParameterizedType.substring( 0,
               potentiallyParameterizedType.indexOf( GENERICS_START ) );
         final List typeParameters = Arrays.asList( potentiallyParameterizedType
               .substring( potentiallyParameterizedType.indexOf( GENERICS_START ) + 1 )
               .replaceAll( TYPE_BRACKETS_AND_WHITESPACE, "" )
               .split( "," ) );
         usedImports.add( rawContainerType );
         usedImports.addAll( typeParameters );
      } else {
         usedImports.add( potentiallyParameterizedType );
      }
   }

   /**
    * Explicitly adds an import.
    *
    * @param clazz the class to add to the imported classes
    */
   public void importExplicit( final Class clazz ) {
      usedImports.add( clazz.getName() );
   }

   /**
    * Explicitly adds an import. If the Class object is known, use {@link #importExplicit(Class)} instead.
    *
    * @param clazz the fully qualified class name to add to the imported classes
    */
   public void importExplicit( final String clazz ) {
      usedImports.add( clazz );
   }

   /**
    * Explicitly adds a static import.
    *
    * @param clazz the class to add to the imported classes
    */
   public void importStaticExplicit( final Class clazz ) {
      usedStaticImports.add( clazz.getName() );
   }

   /**
    * Returns all used imports EXCEPT for imports of other generated classes as those will reside in the same target
    * package.
    *
    * @return the used imports
    */
   public List getUsedImports() {
      return usedImports.stream().filter( usedImport -> usedImport.contains( "." ) ).collect( Collectors.toList() );
   }

   /**
    * Returns all used imports EXCEPT for imports of other generated classes and those from {@code java.lang} as they
    * are implicitly imported and don't need to be added to the list of imports.
    *
    * The imports are returned in natural order.
    *
    * @return the used imports without classes from {@code java.lang}
    */
   public List getUsedImportsWithoutJavaLang() {
      return getUsedImports().stream().filter( usedImport -> !usedImport.startsWith( "java.lang." ) ).sorted()
                             .collect( Collectors.toList() );
   }

   /**
    * Returns all used static imports.
    *
    * @return the used static imports
    */
   public List getUsedStaticImports() {
      return usedStaticImports.stream().sorted().collect( Collectors.toList() );
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy