Search in sources :

Example 1 with JaxbHbmNativeQueryPropertyReturnType

use of org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryPropertyReturnType in project hibernate-orm by hibernate.

the class ResultSetMappingBinder method extractPropertyResults.

@SuppressWarnings("unchecked")
private static Map<String, String[]> extractPropertyResults(String alias, NativeQueryNonScalarRootReturn rtnSource, PersistentClass pc, HbmLocalMetadataBuildingContext context) {
    if (CollectionHelper.isEmpty(rtnSource.getReturnProperty())) {
        return null;
    }
    final HashMap results = new HashMap();
    List<JaxbHbmNativeQueryPropertyReturnType> propertyReturnSources = new ArrayList<JaxbHbmNativeQueryPropertyReturnType>();
    List<String> propertyNames = new ArrayList<String>();
    for (JaxbHbmNativeQueryPropertyReturnType propertyReturnSource : rtnSource.getReturnProperty()) {
        final int dotPosition = propertyReturnSource.getName().lastIndexOf('.');
        if (pc == null || dotPosition == -1) {
            propertyReturnSources.add(propertyReturnSource);
            propertyNames.add(propertyReturnSource.getName());
        } else {
            final String reducedName = propertyReturnSource.getName().substring(0, dotPosition);
            final Value value = pc.getRecursiveProperty(reducedName).getValue();
            Iterator parentPropItr;
            if (value instanceof Component) {
                final Component comp = (Component) value;
                parentPropItr = comp.getPropertyIterator();
            } else if (value instanceof ToOne) {
                final ToOne toOne = (ToOne) value;
                final PersistentClass referencedPc = context.getMetadataCollector().getEntityBinding(toOne.getReferencedEntityName());
                if (toOne.getReferencedPropertyName() != null) {
                    try {
                        parentPropItr = ((Component) referencedPc.getRecursiveProperty(toOne.getReferencedPropertyName()).getValue()).getPropertyIterator();
                    } catch (ClassCastException e) {
                        throw new MappingException("dotted notation reference neither a component nor a many/one to one", e, context.getOrigin());
                    }
                } else {
                    try {
                        if (referencedPc.getIdentifierMapper() == null) {
                            parentPropItr = ((Component) referencedPc.getIdentifierProperty().getValue()).getPropertyIterator();
                        } else {
                            parentPropItr = referencedPc.getIdentifierMapper().getPropertyIterator();
                        }
                    } catch (ClassCastException e) {
                        throw new MappingException("dotted notation reference neither a component nor a many/one to one", e, context.getOrigin());
                    }
                }
            } else {
                throw new MappingException("dotted notation reference neither a component nor a many/one to one", context.getOrigin());
            }
            boolean hasFollowers = false;
            List<String> followers = new ArrayList<String>();
            while (parentPropItr.hasNext()) {
                final Property parentProperty = (Property) parentPropItr.next();
                final String currentPropertyName = parentProperty.getName();
                final String currentName = reducedName + '.' + currentPropertyName;
                if (hasFollowers) {
                    followers.add(currentName);
                }
                if (propertyReturnSource.getName().equals(currentName)) {
                    hasFollowers = true;
                }
            }
            int index = propertyNames.size();
            for (String follower : followers) {
                int currentIndex = getIndexOfFirstMatchingProperty(propertyNames, follower);
                index = currentIndex != -1 && currentIndex < index ? currentIndex : index;
            }
            propertyNames.add(index, propertyReturnSource.getName());
            propertyReturnSources.add(index, propertyReturnSource);
        }
    }
    Set<String> uniqueReturnProperty = new HashSet<String>();
    for (JaxbHbmNativeQueryPropertyReturnType propertyReturnBinding : propertyReturnSources) {
        final String name = propertyReturnBinding.getName();
        if ("class".equals(name)) {
            throw new MappingException("class is not a valid property name to use in a <return-property>, use <return-discriminator> instead", context.getOrigin());
        }
        //TODO: validate existing of property with the chosen name. (secondpass )
        ArrayList allResultColumns = extractResultColumns(propertyReturnBinding);
        if (allResultColumns.isEmpty()) {
            throw new MappingException(String.format(Locale.ENGLISH, "return-property [alias=%s, property=%s] must specify at least one column or return-column name", alias, propertyReturnBinding.getName()), context.getOrigin());
        }
        if (uniqueReturnProperty.contains(name)) {
            throw new MappingException(String.format(Locale.ENGLISH, "Duplicate return-property [alias=%s] : %s", alias, propertyReturnBinding.getName()), context.getOrigin());
        }
        uniqueReturnProperty.add(name);
        // the issue here is that for <return-join/> representing an entity collection,
        // the collection element values (the property values of the associated entity)
        // are represented as 'element.{propertyname}'.  Thus the StringHelper.root()
        // here puts everything under 'element' (which additionally has significant
        // meaning).  Probably what we need to do is to something like this instead:
        //      String root = StringHelper.root( name );
        //      String key = root; // by default
        //      if ( !root.equals( name ) ) {
        //	        // we had a dot
        //          if ( !root.equals( alias ) {
        //              // the root does not apply to the specific alias
        //              if ( "elements".equals( root ) {
        //                  // we specifically have a <return-join/> representing an entity collection
        //                  // and this <return-property/> is one of that entity's properties
        //                  key = name;
        //              }
        //          }
        //      }
        // but I am not clear enough on the intended purpose of this code block, especially
        // in relation to the "Reorder properties" code block above...
        //			String key = StringHelper.root( name );
        ArrayList intermediateResults = (ArrayList) results.get(name);
        if (intermediateResults == null) {
            results.put(name, allResultColumns);
        } else {
            intermediateResults.addAll(allResultColumns);
        }
    }
    for (Object o : results.entrySet()) {
        Map.Entry entry = (Map.Entry) o;
        if (entry.getValue() instanceof ArrayList) {
            ArrayList list = (ArrayList) entry.getValue();
            entry.setValue(list.toArray(new String[list.size()]));
        }
    }
    return results.isEmpty() ? Collections.EMPTY_MAP : results;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) JaxbHbmNativeQueryPropertyReturnType(org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryPropertyReturnType) MappingException(org.hibernate.boot.MappingException) Value(org.hibernate.mapping.Value) Iterator(java.util.Iterator) ToOne(org.hibernate.mapping.ToOne) Component(org.hibernate.mapping.Component) Property(org.hibernate.mapping.Property) HashMap(java.util.HashMap) Map(java.util.Map) PersistentClass(org.hibernate.mapping.PersistentClass) HashSet(java.util.HashSet)

Aggregations

ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 MappingException (org.hibernate.boot.MappingException)1 JaxbHbmNativeQueryPropertyReturnType (org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryPropertyReturnType)1 Component (org.hibernate.mapping.Component)1 PersistentClass (org.hibernate.mapping.PersistentClass)1 Property (org.hibernate.mapping.Property)1 ToOne (org.hibernate.mapping.ToOne)1 Value (org.hibernate.mapping.Value)1