Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at http://www.eclipse.org/org/documents/edl-v10.php. Contributors: 08/10/2009-2.0 Guy Pelletier - 267391: JPA 2.0 implement/extend/use an APT tooling library for MetaModel API canonical classes 06/01/2010-2.1 Guy Pelletier - 315195: Add new property to avoid reading XML during the canonical model generation 08/25/2010-2.2 Guy Pelletier - 309445: CannonicalModelProcessor process all files 11/23/2010-2.2 Guy Pelletier - 330660: Canonical model generator throws ClassCastException when using package-info.java 04/01/2011-2.3 Guy Pelletier - 337323: Multi-tenant with shared schema support (part 2) 09/20/2011-2.3.1 Guy Pelletier - 357476: Change caching default to ISOLATED for multitenant's using a shared EMF. /
   
 package org.eclipse.persistence.internal.jpa.modelgen;
 
 import java.util.List;
 import java.util.Map;
 
 
 import  org.eclipse.persistence.internal.jpa.modelgen.MetadataMirrorFactory;
This metadata factory employs java mirrors to create MetadataClass and is used with the canonical model processor.

Author(s):
Guy Pelletier
Since:
EclipseLink 1.2
 
 public class MetadataMirrorFactory extends MetadataFactory {
     
     // Thing to note: persistence units can be reloaded. We do not however
     // reload their associated projects. Once the project is created, it remains 
     // around for the lifecycle of the compiler.
     
     // This is a map of element/metadata classes built per compile round. This 
     // map is cleared for each compile round.
     private Map<ElementMetadataClassroundElements;
     
     // This is a hash set of metadata classes per compile round. This set is
     // cleared for each compile round.
     
     private ProcessingEnvironment processingEnv;

    
INTERNAL: The factory is kept as a static object to the persistence unit. The first time the factory is initialized, we will get a full list of root elements. Build MetadataClass for them right away. We don't want to rebuild the factory every time otherwise we lose already built metadata classes and may not be able to rebuild till individual elements are 'touched' or if the project is rebuilt as a whole.
 
     protected MetadataMirrorFactory(MetadataLogger loggerClassLoader loader) {
         super(loggerloader);
          = new HashMap<ElementMetadataClass>();
          = new HashSet<MetadataClass>();
          = new HashMap<StringPersistenceUnit>();
          = new HashMap<StringMetadataProject>();
     }
    
    
INTERNAL:
 
    public void addPersistenceUnit(SEPersistenceUnitInfo puInfoPersistenceUnit persistenceUnit) {
        .put(puInfo.getPersistenceUnitName(), persistenceUnit);
    }
    
    
INTERNAL: If the metadata class doesn't exist for the given element, we will build one and add it to our map of MetadataClasses before returning it. We keep our own map of metadata classes for each round element for a couple reasons: 1- Most importantly, we use this map to avoid an infinite loop. Once we kick off the visiting of a class, it snow balls into visiting and building other classes from the round (referenced from that class). 2- For our own safety we cache metadata class keyed on the element we built it for. This ensures we are always dealing with the correct related metadata class. 3- For each round we must update all metadata classes for each round element.
    public MetadataClass getMetadataClass(Element element) {
        MetadataClass metadataClass = .get(element);
        
        if (metadataClass == null) {
            // Only log if logging on finest.
            boolean shouldLog = getLogger().getSession().getLogLevel() == .;
            // As a performance gain, avoid visiting this class if it is not a 
            // round element. We must re-visit round elements.
            if (isRoundElement(element)) {
                if (shouldLog) {
                    .getMessager().printMessage(."Building metadata class for round element: " + element);
                }
                metadataClass = new MetadataClass(MetadataMirrorFactory.this"");
                .put(elementmetadataClass);
                .add(metadataClass);
                
                // Kick off the visiting of elements.
                element.accept(metadataClass);
              
                // The name of the metadata class is a qualified name from a 
                // type element. Set this name on the MetadataFactory map. We 
                // can't call addMetadataClass till we have visited the class.
                addMetadataClass(metadataClass);
            } else {
                String name = element.toString();
                if (metadataClassExists(name))  {
                    return getMetadataClass(name);
                }
                // So we are not a round element, the outcome is as follows:
                //  - TypeElement or TypeParameterElement in existing class map, 
                //    return it.
                //  - TypeElement, and not in the existing class map, return 
                //    simple non-visited MetadataClass with only a name/type.
                //  - TypeParameterElement, and not in the existing class map,
                //    visit it to ensure we get the correct generic type set
                //    and return it.
                //  - Everything else, return simple non-visited MetadataClass 
                //    with only a name/type from the toString value.
                if (element instanceof TypeElement || element instanceof TypeParameterElement) {
                    if (element instanceof TypeElement) {
                        if (shouldLog) {
                            .getMessager().printMessage(."Building metadata class for type element: " + name);
                        }
                        metadataClass = new MetadataClass(MetadataMirrorFactory.thisname);
                        addMetadataClass(metadataClass);
                        element.accept(metadataClass);
                        addMetadataClass(metadataClass);
                    } else {
                        // Only thing going to get through at this point are
                        // TypeParameterElements (presumably generic ones). Look 
                        // at those further since they 'should' be simple visits.
                        if (shouldLog) {
                            .getMessager().printMessage(."Building type parameter element: " + name);
                        }
                        metadataClass = new MetadataClass(MetadataMirrorFactory.thisname);
                        addMetadataClass(metadataClass);
                        element.accept(metadataClass);
                        addMetadataClass(metadataClass);
                    }
                } else {
                    // Array types etc ...
                    metadataClass = getMetadataClass(element.toString());
                }
            }
        }
        
        return metadataClass;
    }
    @Override
    public MetadataClass getMetadataClass(String classNameboolean isLazy) {
        return getMetadataClass(className);
    }
    
    
INTERNAL: This assumes that every class that is accessed in the pre-process methods will have a class metadata built for them already. That is, our visitor must visit every class that the pre-process will want to look at. All return types and field types need a metadata class or else kaboom, null pointer!
    @Override
    public MetadataClass getMetadataClass(String className) {
        if (className == null) {
            return null;
        } else {
        	if (! metadataClassExists(className)) {
        		// By the time this method is called we should have built a 
        		// MetadataClass for all the model elements (and then some) which 
        		// are the only classes we really care about. This is acting like a 
        		// catch all for any jdk classes we didn't visit and just returns a 
        		// MetadataClass with the same class name.
        		addMetadataClass(new MetadataClass(thisclassName));
        	}
        	
        	return getMetadataClasses().get(className);
        }
    }
    
    
INTERNAL: If the adds a new element will build it and add it to our list of MetadataClasses.
    public MetadataClass getMetadataClass(TypeMirror typeMirror) {
        Element element = .getTypeUtils().asElement(typeMirror);
        
        if (element == null) {
            // This case hits when we are passed a TypeMirror of <none>. Not
            // 100% on the whole story here, either way we create a metadata 
            // class with that name and carry on. The case also hits when we 
            // ask for a metadata class for array types.  
            return getMetadataClass(typeMirror.toString());
        } else {
            return getMetadataClass(element);
        }
    }
    
    
INTERNAL: We preserve state from each processor run by holding static references to projects.
        if (! .containsKey(puInfo.getPersistenceUnitName())) {
            MetadataProject project = new MetadataProject(puInfonew ServerSession(new Project(new DatabaseLogin())), falsefalsefalsefalsefalse);
            .put(puInfo.getPersistenceUnitName(), project);
            return project;
        } else {
            return .get(puInfo.getPersistenceUnitName());
        }
    }
    
    
INTERNAL:
        return .values();
    }
    
    
INTERNAL:
        return ;
    }
    
    
INTERNAL:
    public Map<ElementMetadataClassgetRoundElements() {
        return ;
    }
    
    
INTENAL:
    public boolean isRoundElement(Element element) {
        return .containsKey(element);
    }
    
    
INTENAL:
    public boolean isRoundElement(MetadataClass cls) {
        return .contains(cls);
    }
    
    
INTERNAL:
    @Override
    public void resolveGenericTypes(MetadataClass childList<StringgenericTypesMetadataClass parentMetadataDescriptor descriptor) {
        // Our metadata factory does not and can not resolve the types since
        // we are writing static attributes on our generated class. This 
        // factory will use types of "? extends Object". So don't need to
        // resolve anything here. No work is good work!
    }
    
    
INTERNAL: Our processor will not visit generated elements, there is no need for us to do this.
    public void setEnvironments(ProcessingEnvironment processingEnvironmentRoundEnvironment roundEnvironment) {
         = processingEnvironment;
        .clear();
        .clear();
        
        // Initialize the element visitor if it is null.
        if ( == null) {
        }
        
        // Go through the root elements and gather the round elements that
        // we care about. It is crucial to not call getMetadataClass(element)
        // before we gather our list of round elements. Calling this method will
        // trigger the visiting of elements which has a dependency on round
        // elements.
        for (Element element : roundEnvironment.getRootElements()) {
            // Look at only class elements.
            if (element.getKind().isClass()) {
                // Don't look at the generated classes. We must look at all the
                // classes and not only those decorated with @Entity, 
                // @MappedSuperclass or @Embeddable, since it may be a class
                // defined solely in XML and we want to make sure we look at
                // the changes for those classes as well.
                if (element.getAnnotation(javax.annotation.Generated.class) == null) { 
                    .put(elementnull);
                }
            }
        }
        
        // Visit all the round elements now. These may be new elements or 
        // existing elements that were changed. We must build or re-build the 
        // class metadata for that element to be re-used with new accessors
        // needing to pre-processed.
        for (Element element : .keySet()) {
            getMetadataClass(element);
        }
    }
New to GrepCode? Check out our FAQ X