/** * Copyright 2012 Red Hat, Inc. and/or its affiliates. * <p/> * 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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 org.kie.workbench.common.screens.datamodeller.client.util; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.kie.workbench.common.screens.datamodeller.model.droolsdomain.DroolsDomainAnnotations; import org.kie.workbench.common.screens.datamodeller.model.maindomain.MainDomainAnnotations; import org.kie.workbench.common.services.datamodel.util.SortHelper; import org.kie.workbench.common.services.datamodeller.core.DataModel; import org.kie.workbench.common.services.datamodeller.core.DataObject; import org.kie.workbench.common.services.datamodeller.core.JavaEnum; import org.kie.workbench.common.services.datamodeller.core.JavaType; import org.kie.workbench.common.services.datamodeller.core.ObjectProperty; import org.kie.workbench.common.services.datamodeller.core.PropertyType; import org.uberfire.backend.vfs.Path; import org.uberfire.commons.data.Pair; public class DataModelerUtils { public static final String EXTERNAL_PREFIX = "- ext - "; public static final String CLIPPED_MARKER = "..."; /* * Returns the data-object's class name or the label, in case the object has one. */ public static String getDataObjectUILabel( DataObject dataObject ) { if ( dataObject != null ) { String label = AnnotationValueHandler.getStringValue( dataObject, MainDomainAnnotations.LABEL_ANNOTATION ); if ( label == null ) { label = dataObject.getName(); } return label; } return ""; } public static String getMaxLengthClippedString( String s, int maxLength ) { return s.length() > maxLength ? s.substring( 0, maxLength ) + CLIPPED_MARKER : s; } public static String getDataObjectFullLabel( DataObject dataObject ) { return getDataObjectFullLabel( dataObject, true ); } /* * Returns the data-object's class name or, in case the object has a label, the label followed by the * class name between brackets. */ public static String getDataObjectFullLabel( DataObject dataObject, boolean includePackage ) { StringBuilder sb = new StringBuilder( "" ); if ( dataObject != null ) { sb.append( includePackage ? dataObject.getClassName() : dataObject.getName() ); String objectLabel = AnnotationValueHandler.getStringValue( dataObject, MainDomainAnnotations.LABEL_ANNOTATION ); if ( objectLabel != null ) { sb.insert( 0, objectLabel + " (" ).append( ")" ); } } return sb.toString(); } public static String assembleClassName( String objPackage, String objName ) { if ( objName == null || objName.length() == 0 ) { return null; } StringBuilder sb = new StringBuilder( objName ); if ( objPackage != null && !"".equals( objPackage ) ) { sb.insert( 0, "." ).insert( 0, objPackage ); } return sb.toString(); } public static String extractClassName( String fullClassName ) { if ( fullClassName == null ) { return null; } int index = fullClassName.lastIndexOf( "." ); if ( index > 0 ) { return fullClassName.substring( index + 1, fullClassName.length() ); } else { return fullClassName; } } public static String extractPackageName( String fullClassName ) { if ( fullClassName == null ) { return null; } int index = fullClassName.lastIndexOf( "." ); if ( index > 0 ) { return fullClassName.substring( 0, index ); } else { return null; } } public static String extractSimpleFileName( Path path ) { if ( path == null ) { return null; } String fileNameWithExtension = path.getFileName(); return fileNameWithExtension.substring( 0, fileNameWithExtension.lastIndexOf( "." ) ); } public static String[] getPackageTerms( String packageName ) { return packageName.split( "\\.", -1 ); } public static String[] calculateSubPackages( String packageName ) { String packageTerms[]; String subpackages[]; if ( packageName == null || ( packageTerms = getPackageTerms( packageName ) ) == null ) { return null; } subpackages = new String[ packageTerms.length ]; for ( int i = 0; i < packageTerms.length; i++ ) { String subpackage = ""; for ( int j = 0; j <= i; j++ ) { subpackage += packageTerms[ j ]; if ( j < i ) { subpackage += "."; } } subpackages[ i ] = subpackage; } return subpackages; } public static String unCapitalize( String str ) { int strLen = str != null ? str.length() : 0; if ( strLen == 0 ) { return str; } if ( strLen > 1 && Character.isUpperCase( str.charAt( 0 ) ) && Character.isUpperCase( str.charAt( 1 ) ) ) { return str; } else { return new StringBuffer( strLen ) .append( Character.toLowerCase( str.charAt( 0 ) ) ) .append( str.substring( 1 ) ) .toString(); } } public static List<ObjectProperty> getFieldsUsingPosition( DataObject dataObject, int position, String skipField ) { List<ObjectProperty> fields = new ArrayList<ObjectProperty>(); if ( dataObject != null && dataObject.getProperties() != null ) { for ( ObjectProperty property : dataObject.getProperties() ) { if ( skipField != null && skipField.equals( property.getName() ) ) { continue; } String currentPosition = AnnotationValueHandler.getStringValue( property.getAnnotation( DroolsDomainAnnotations.POSITION_ANNOTATION ), DroolsDomainAnnotations.VALUE_PARAM ); if ( currentPosition != null && currentPosition.trim().equals( position + "" ) ) { fields.add( property ); } } } return fields; } public static Integer getMaxPosition( DataObject dataObject ) { List<ObjectProperty> properties = dataObject.getProperties(); Integer maxPosition = -1; Integer currentPosition; if ( properties != null && properties.size() > 0 ) { for ( ObjectProperty property : properties ) { try { currentPosition = new Integer( AnnotationValueHandler.getStringValue( property, DroolsDomainAnnotations.POSITION_ANNOTATION, "value", "-1" ) ); } catch ( Exception e ) { currentPosition = -1; } if ( currentPosition > maxPosition ) { maxPosition = currentPosition; } } } return maxPosition; } public static boolean hasPosition( ObjectProperty property ) { return property != null && property.getAnnotation( DroolsDomainAnnotations.POSITION_ANNOTATION ) != null; } public static List<ObjectProperty> getManagedProperties( DataObject dataObject ) { List<ObjectProperty> editableProperties = new ArrayList<ObjectProperty>(); if ( dataObject != null && dataObject.getProperties() != null ) { for ( ObjectProperty property : dataObject.getProperties() ) { if ( isManagedProperty( property ) ) { editableProperties.add( property ); } } } return editableProperties; } public static boolean isManagedProperty( ObjectProperty property ) { return !property.isFinal() && !property.isStatic(); } public static String calculateExpectedClassName( Path projectRootPath, Path javaFilePath ) { if ( projectRootPath == null || javaFilePath == null ) { return null; } return calculateExpectedClassName( projectRootPath.toURI(), javaFilePath.toURI() ); } public static String calculateExpectedClassName( String projectRootPathUri, String javaFilePathUri ) { String srcPathStrUri = projectRootPathUri + "/src/main/java/"; if ( !javaFilePathUri.startsWith( srcPathStrUri ) ) { return null; } javaFilePathUri = javaFilePathUri.substring( srcPathStrUri.length(), javaFilePathUri.length() ); int extensionIndex = javaFilePathUri.lastIndexOf( ".java" ); if ( extensionIndex <= 0 ) { return null; } javaFilePathUri = javaFilePathUri.substring( 0, extensionIndex ); return javaFilePathUri.replaceAll( "/", "." ); } public static List<ObjectProperty> filterPropertiesByType( Collection<ObjectProperty> properties, List<String> expectedTypes, boolean skipUnmanaged ) { final ArrayList<ObjectProperty> result = new ArrayList<ObjectProperty>(); if ( properties == null || properties.size() == 0 ) { return result; } final Map<String, String> types = new HashMap<String, String>(); if ( expectedTypes != null && expectedTypes.size() > 0 ) { for ( String type : expectedTypes ) { types.put( type, type ); } } else { return result; } for ( ObjectProperty propertyTO : properties ) { if ( propertyTO.getClassName() != null && types.containsKey( propertyTO.getClassName() ) ) { if ( skipUnmanaged && ( ReflectionUtil.isStatic( propertyTO.getModifiers() ) || ReflectionUtil.isFinal( propertyTO.getModifiers() ) ) ) { continue; } result.add( propertyTO ); } } return result; } public static List<Pair<String, String>> buildFieldTypeOptions( final Collection<PropertyType> baseTypes, final Collection<DataObject> dataObjects, final Collection<JavaEnum> javaEnum, final Collection<DataObject> externalClasses, final Collection<JavaEnum> externalEnums, final boolean includeEmptyItem ) { return buildFieldTypeOptions( baseTypes, dataObjects, javaEnum, externalClasses, externalEnums, null, includeEmptyItem ); } public static List<Pair<String, String>> buildFieldTypeOptions( final Collection<PropertyType> baseTypes, final Collection<DataObject> dataObjects, final Collection<JavaEnum> javaEnums, final Collection<DataObject> externalClasses, final Collection<JavaEnum> externalEnums, final String selectedType, final boolean includeEmptyItem ) { List<Pair<String, String>> typeList = new ArrayList<Pair<String, String>>( ); Collection<JavaType> javaTypes = new ArrayList<JavaType>( ); Collection<JavaType> externalJavaTypes = new ArrayList<JavaType>( ); SortedMap<String, String> sortedModelTypeNames = new TreeMap<String, String>( SortHelper.ALPHABETICAL_ORDER_COMPARATOR ); SortedMap<String, String> sortedExternalTypeNames = new TreeMap<String, String>( SortHelper.ALPHABETICAL_ORDER_COMPARATOR ); Map<String, PropertyType> orderedBaseTypes = new TreeMap<String, PropertyType>( SortHelper.ALPHABETICAL_ORDER_COMPARATOR ); Map<String, PropertyType> baseTypesByClassName = new TreeMap<String, PropertyType>( SortHelper.ALPHABETICAL_ORDER_COMPARATOR ); boolean selectedTypeIncluded = false; if ( includeEmptyItem ) { typeList.add( UIUtil.emptyValue() ); } if ( baseTypes != null ) { for ( PropertyType type : baseTypes ) { orderedBaseTypes.put( type.getName(), type ); baseTypesByClassName.put( type.getClassName(), type ); } } // First add all base types, ordered for ( Map.Entry<String, PropertyType> baseType : orderedBaseTypes.entrySet() ) { if ( !baseType.getValue().isPrimitive() ) { typeList.add( new Pair( baseType.getKey(), baseType.getValue().getClassName() ) ); } } // collect all model types, ordered if ( dataObjects != null ) { javaTypes.addAll( dataObjects ); } if ( javaEnums != null ) { javaTypes.addAll( javaEnums ); } for ( JavaType javaType : javaTypes ) { String className = javaType.getClassName(); String classLabel; if ( javaType instanceof DataObject ) { classLabel = DataModelerUtils.getDataObjectFullLabel( (DataObject) javaType ); } else { classLabel = javaType.getClassName(); } sortedModelTypeNames.put( classLabel, className ); if ( selectedType != null && selectedType.equals( className ) ) { selectedTypeIncluded = true; } } // collect external types, ordered if ( externalClasses != null ) { externalJavaTypes.addAll( externalClasses ); } if ( externalEnums != null ) { externalJavaTypes.addAll( externalEnums ); } if ( externalClasses != null ) { for ( JavaType externalJavaType : externalJavaTypes ) { String extClass = externalJavaType.getClassName(); sortedExternalTypeNames.put( DataModelerUtils.EXTERNAL_PREFIX + extClass, extClass ); if ( selectedType != null && selectedType.equals( extClass ) ) { selectedTypeIncluded = true; } } } //check selectedType isn't present if ( selectedType != null && !selectedTypeIncluded && !baseTypesByClassName.containsKey( selectedType ) ) { //uncommon case. A field was loaded but the class isn't within the model or external classes. String extClass = selectedType; sortedExternalTypeNames.put( DataModelerUtils.EXTERNAL_PREFIX + extClass, extClass ); } //add project classes to the selector. for ( Map.Entry<String, String> typeName : sortedModelTypeNames.entrySet() ) { typeList.add( new Pair<String, String>( typeName.getKey(), typeName.getValue() ) ); } //add external classes to the selector. for ( Map.Entry<String, String> typeName : sortedExternalTypeNames.entrySet() ) { typeList.add( new Pair<String, String>( typeName.getKey(), typeName.getValue() ) ); } //finally add primitives for ( Map.Entry<String, PropertyType> baseType : orderedBaseTypes.entrySet() ) { if ( baseType.getValue().isPrimitive() ) { typeList.add( new Pair<String, String>( baseType.getKey(), baseType.getValue().getClassName() ) ); } } return typeList; } public static List<Pair<String, String>> buildSuperclassOptions( DataModel dataModel, DataObject currentDataObject ) { List<Pair<String, String>> options = new ArrayList<Pair<String, String>>(); if ( dataModel != null ) { SortedMap<String, String> sortedModelClasses = new TreeMap<String, String>( SortHelper.ALPHABETICAL_ORDER_COMPARATOR ); SortedMap<String, String> sortedExternalClasses = new TreeMap<String, String>( SortHelper.ALPHABETICAL_ORDER_COMPARATOR ); boolean isExtensible = false; String className; String classLabel; String currentClassName; // first, all data objects form this model in order for ( DataObject internalDataObject : dataModel.getDataObjects() ) { className = internalDataObject.getClassName(); classLabel = getDataObjectFullLabel( internalDataObject ); isExtensible = !internalDataObject.isAbstract() && !internalDataObject.isFinal() && !internalDataObject.isInterface(); if ( isExtensible ) { if ( currentDataObject != null && className.toLowerCase().equals( currentDataObject.getClassName().toLowerCase() ) ) continue; sortedModelClasses.put( classLabel, className ); } } // Then add all external types, ordered for ( DataObject externalDataObject : dataModel.getExternalClasses() ) { className = externalDataObject.getClassName(); classLabel = EXTERNAL_PREFIX + className; isExtensible = !externalDataObject.isAbstract() && !externalDataObject.isFinal() && !externalDataObject.isInterface(); if ( isExtensible ) { if ( currentDataObject != null && className.toLowerCase().equals( currentDataObject.getClassName().toLowerCase() ) ) continue; sortedExternalClasses.put( classLabel, className ); } } if ( currentDataObject != null && currentDataObject.getSuperClassName() != null ) { currentClassName = currentDataObject.getSuperClassName(); if ( !sortedModelClasses.containsKey( currentClassName ) && !sortedExternalClasses.containsKey( currentClassName ) ) { //the model was loaded but the super class is not a model class nor an external class, e.g. java.lang.Object. Still needs to be loaded. sortedModelClasses.put( currentClassName, currentClassName ); } } for ( Map.Entry<String, String> classNameEntry : sortedModelClasses.entrySet() ) { options.add( new Pair( classNameEntry.getKey(), classNameEntry.getValue()) ); } for ( Map.Entry<String, String> classNameEntry : sortedExternalClasses.entrySet() ) { options.add( new Pair( classNameEntry.getKey(), classNameEntry.getValue()) ); } } return options; } public static final String nullTrim( String value ) { String result = value != null ? value.trim() : value; if ( result != null && !"".equals( result ) ) { return result; } else { return null; } } public static final String trim( String value ) { return value != null ? value.trim() : value; } }