Package org.apache.olingo.odata2.processor.core.jpa.model

Source Code of org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmProperty

/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.apache.olingo.odata2.processor.core.jpa.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
import org.apache.olingo.odata2.api.edm.FullQualifiedName;
import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
import org.apache.olingo.odata2.api.edm.provider.ComplexType;
import org.apache.olingo.odata2.api.edm.provider.Property;
import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationEndView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexPropertyView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView;
import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
import org.apache.olingo.odata2.processor.core.jpa.access.model.JPATypeConvertor;

public class JPAEdmProperty extends JPAEdmBaseViewImpl implements
    JPAEdmPropertyView, JPAEdmComplexPropertyView {

  private JPAEdmSchemaView schemaView;
  private JPAEdmEntityTypeView entityTypeView;
  private JPAEdmComplexTypeView complexTypeView;
  private JPAEdmNavigationPropertyView navigationPropertyView = null;

  private JPAEdmKeyView keyView;
  private List<Property> properties;
  private SimpleProperty currentSimpleProperty = null;
  private ComplexProperty currentComplexProperty = null;
  private Attribute<?, ?> currentAttribute;
  private boolean isBuildModeComplexType;
  private Map<String, Integer> associationCount;

  public JPAEdmProperty(final JPAEdmSchemaView view) {
    super(view);
    schemaView = view;
    entityTypeView = schemaView.getJPAEdmEntityContainerView()
        .getJPAEdmEntitySetView().getJPAEdmEntityTypeView();
    complexTypeView = schemaView.getJPAEdmComplexTypeView();
    navigationPropertyView = new JPAEdmNavigationProperty(schemaView);
    isBuildModeComplexType = false;
    associationCount = new HashMap<String, Integer>();
  }

  public JPAEdmProperty(final JPAEdmSchemaView schemaView,
      final JPAEdmComplexTypeView view) {
    super(view);
    this.schemaView = schemaView;
    complexTypeView = view;
    isBuildModeComplexType = true;
  }

  @Override
  public JPAEdmBuilder getBuilder() {
    if (builder == null) {
      builder = new JPAEdmPropertyBuilder();
    }

    return builder;
  }

  @Override
  public List<Property> getEdmPropertyList() {
    return properties;
  }

  @Override
  public JPAEdmKeyView getJPAEdmKeyView() {
    return keyView;
  }

  @Override
  public SimpleProperty getEdmSimpleProperty() {
    return currentSimpleProperty;
  }

  @Override
  public Attribute<?, ?> getJPAAttribute() {
    return currentAttribute;
  }

  @Override
  public ComplexProperty getEdmComplexProperty() {
    return currentComplexProperty;
  }

  @Override
  public JPAEdmNavigationPropertyView getJPAEdmNavigationPropertyView() {
    return navigationPropertyView;
  }

  private class JPAEdmPropertyBuilder implements JPAEdmBuilder {
    /*
     *
     * Each call to build method creates a new EDM Property List.
     * The Property List can be created either by an Entity type or
     * ComplexType. The flag isBuildModeComplexType tells if the
     * Properties are built for complex type or for Entity Type.
     *
     * While Building Properties Associations are built. However
     * the associations thus built does not contain Referential
     * constraint. Associations thus built only contains
     * information about Referential constraints. Adding of
     * referential constraints to Associations is the taken care
     * by Schema.
     *
     * Building Properties is divided into four parts
     * A) Building Simple Properties
     * B) Building Complex Properties
     * C) Building Associations
     * D) Building Navigation Properties
     *
     * ************************************************************
     * Build EDM Schema - STEPS
     * ************************************************************
     * A) Building Simple Properties:
     *
     * 1) Fetch JPA Attribute List from
     * A) Complex Type
     * B) Entity Type
     * depending on isBuildModeComplexType.
     * B) Building Complex Properties
     * C) Building Associations
     * D) Building Navigation Properties
     *
     * ************************************************************
     * Build EDM Schema - STEPS
     * ************************************************************
     */
    @Override
    public void build() throws ODataJPAModelException, ODataJPARuntimeException {

      JPAEdmBuilder keyViewBuilder = null;

      properties = new ArrayList<Property>();

      List<Attribute<?, ?>> jpaAttributes = null;
      String currentEntityName = null;
      String targetEntityName = null;
      String entityTypeName = null;
      if (isBuildModeComplexType) {
        jpaAttributes = sortInAscendingOrder(complexTypeView.getJPAEmbeddableType()
            .getAttributes());
        entityTypeName = complexTypeView.getJPAEmbeddableType().getJavaType()
            .getSimpleName();
      } else {
        jpaAttributes = sortInAscendingOrder(entityTypeView.getJPAEntityType()
            .getAttributes());
        entityTypeName = entityTypeView.getJPAEntityType().getName();
      }

      for (Object jpaAttribute : jpaAttributes) {
        currentAttribute = (Attribute<?, ?>) jpaAttribute;

        // Check for need to Exclude
        if (isExcluded((JPAEdmPropertyView) JPAEdmProperty.this, entityTypeName, currentAttribute.getName())) {
          continue;
        }

        PersistentAttributeType attributeType = currentAttribute
            .getPersistentAttributeType();

        switch (attributeType) {
        case BASIC:

          currentSimpleProperty = new SimpleProperty();
          JPAEdmNameBuilder
              .build((JPAEdmPropertyView) JPAEdmProperty.this, isBuildModeComplexType);

          EdmSimpleTypeKind simpleTypeKind = JPATypeConvertor
              .convertToEdmSimpleType(currentAttribute
                  .getJavaType(), currentAttribute);

          currentSimpleProperty.setType(simpleTypeKind);
          JPAEdmFacets.setFacets(currentAttribute, currentSimpleProperty);

          properties.add(currentSimpleProperty);

          if (((SingularAttribute<?, ?>) currentAttribute).isId()) {
            if (keyView == null) {
              keyView = new JPAEdmKey(JPAEdmProperty.this);
              keyViewBuilder = keyView.getBuilder();
            }

            keyViewBuilder.build();
          }

          break;
        case EMBEDDED:
          ComplexType complexType = complexTypeView
              .searchEdmComplexType(currentAttribute.getJavaType().getName());

          if (complexType == null) {
            JPAEdmComplexTypeView complexTypeViewLocal = new JPAEdmComplexType(
                schemaView, currentAttribute);
            complexTypeViewLocal.getBuilder().build();
            complexType = complexTypeViewLocal.getEdmComplexType();
            complexTypeView.addJPAEdmCompleTypeView(complexTypeViewLocal);

          }

          if (isBuildModeComplexType == false
              && entityTypeView.getJPAEntityType().getIdType()
                  .getJavaType()
                  .equals(currentAttribute.getJavaType())) {

            if (keyView == null) {
              keyView = new JPAEdmKey(complexTypeView,
                  JPAEdmProperty.this);
            }
            keyView.getBuilder().build();
            complexTypeView.expandEdmComplexType(complexType, properties, currentAttribute.getName());
          } else {
            currentComplexProperty = new ComplexProperty();
            if (isBuildModeComplexType) {
              JPAEdmNameBuilder
                  .build((JPAEdmComplexPropertyView) JPAEdmProperty.this,
                      complexTypeView.getJPAEmbeddableType().getJavaType().getSimpleName());
            } else {
              JPAEdmNameBuilder
                  .build((JPAEdmComplexPropertyView) JPAEdmProperty.this,
                      JPAEdmProperty.this);
            }
            currentComplexProperty.setType(new FullQualifiedName(
                schemaView.getEdmSchema().getNamespace(),
                complexType.getName()));

            properties.add(currentComplexProperty);
            List<String> nonKeyComplexTypes = schemaView.getNonKeyComplexTypeList();
            if (!nonKeyComplexTypes.contains(currentComplexProperty.getType().getName()))
            {
              schemaView.addNonKeyComplexName(currentComplexProperty.getType().getName());
            }
          }

          break;
        case MANY_TO_MANY:
        case ONE_TO_MANY:
        case ONE_TO_ONE:
        case MANY_TO_ONE:

          JPAEdmAssociationEndView associationEndView = new JPAEdmAssociationEnd(entityTypeView, JPAEdmProperty.this);
          associationEndView.getBuilder().build();
          JPAEdmAssociationView associationView = schemaView.getJPAEdmAssociationView();
          if (associationView.searchAssociation(associationEndView) == null) {
            int count = associationView.getNumberOfAssociationsWithSimilarEndPoints(associationEndView);
            JPAEdmAssociationView associationViewLocal =
                new JPAEdmAssociation(associationEndView, entityTypeView, JPAEdmProperty.this, count);
            associationViewLocal.getBuilder().build();
            associationView.addJPAEdmAssociationView(associationViewLocal, associationEndView);
          }

          JPAEdmReferentialConstraintView refConstraintView = new JPAEdmReferentialConstraint(
              associationView, entityTypeView, JPAEdmProperty.this);
          refConstraintView.getBuilder().build();

          if (refConstraintView.isExists()) {
            associationView.addJPAEdmRefConstraintView(refConstraintView);
          }

          if (navigationPropertyView == null) {
            navigationPropertyView = new JPAEdmNavigationProperty(schemaView);
          }
          currentEntityName = entityTypeView.getJPAEntityType().getName();

          if (currentAttribute.isCollection()) {
            targetEntityName = ((PluralAttribute<?, ?, ?>) currentAttribute).getElementType().getJavaType()
                .getSimpleName();
          } else {
            targetEntityName = currentAttribute.getJavaType().getSimpleName();
          }
          Integer sequenceNumber = associationCount.get(currentEntityName + targetEntityName);
          if (sequenceNumber == null) {
            sequenceNumber = new Integer(1);
          } else {
            sequenceNumber = new Integer(sequenceNumber.intValue() + 1);
          }
          associationCount.put(currentEntityName + targetEntityName, sequenceNumber);
          JPAEdmNavigationPropertyView localNavigationPropertyView =
              new JPAEdmNavigationProperty(associationView, JPAEdmProperty.this, sequenceNumber.intValue());
          localNavigationPropertyView.getBuilder().build();
          navigationPropertyView.addJPAEdmNavigationPropertyView(localNavigationPropertyView);
          break;
        default:
          break;
        }
      }

    }

    @SuppressWarnings("rawtypes")
    private List<Attribute<?, ?>> sortInAscendingOrder(final Set<?> jpaAttributes) {
      List<Attribute<?, ?>> jpaAttributeList = new ArrayList<Attribute<?, ?>>();
      Iterator itr = null;
      Attribute<?, ?> smallestJpaAttribute;
      Attribute<?, ?> currentJpaAttribute;
      while (!jpaAttributes.isEmpty()) {
        itr = jpaAttributes.iterator();
        smallestJpaAttribute = (Attribute<?, ?>) itr.next();
        while (itr.hasNext()) {
          currentJpaAttribute = (Attribute<?, ?>) itr.next();
          if (smallestJpaAttribute.getName().compareTo(currentJpaAttribute.getName()) > 0) {
            smallestJpaAttribute = currentJpaAttribute;
          }
        }
        jpaAttributeList.add(smallestJpaAttribute);
        jpaAttributes.remove(smallestJpaAttribute);
      }
      return jpaAttributeList;
    }
  }

  @Override
  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
    return entityTypeView;
  }

  @Override
  public JPAEdmComplexTypeView getJPAEdmComplexTypeView() {
    return complexTypeView;
  }

  private boolean isExcluded(final JPAEdmPropertyView jpaEdmPropertyView, final String jpaEntityTypeName,
      final String jpaAttributeName) {
    JPAEdmMappingModelAccess mappingModelAccess = jpaEdmPropertyView
        .getJPAEdmMappingModelAccess();
    boolean isExcluded = false;
    if (mappingModelAccess != null && mappingModelAccess.isMappingModelExists()) {
      // Exclusion of a simple property in a complex type
      if (isBuildModeComplexType
          && mappingModelAccess.checkExclusionOfJPAEmbeddableAttributeType(jpaEntityTypeName, jpaAttributeName)
          // Exclusion of a simple property of an Entity Type
          || (!isBuildModeComplexType && mappingModelAccess.checkExclusionOfJPAAttributeType(jpaEntityTypeName,
              jpaAttributeName))) {
        isExcluded = true;
      }
    }
    return isExcluded;
  }
}
TOP

Related Classes of org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmProperty

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.