com.salesforce.apt.graph.model.DefinitionModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of AptSpringModel Show documentation
Show all versions of AptSpringModel Show documentation
This is the spring agnostic 'meat' of the project. It models and analyzes a graph of declarations of object (bean)
definitions, as well as the graph of the objects (beans) themselves.
This project should be reusable in CDI or any other DI/IoC annotation based system.
/*
* Copyright © 2017, Saleforce.com, Inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.salesforce.apt.graph.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.TypeElement;
public class DefinitionModel extends AbstractModel {
private final List objectDefinitions = new ArrayList<>();
private final List expectedDefinitions = new ArrayList<>();
private final List dependencyNames = new ArrayList<>();
//because this field is transient, deserializers will not set it. We must
//carefully account for this by setting the value anywhere it may be used.
private transient List dependencies;
private final List providedInstances = new ArrayList<>();
private final Set computedExpected = new HashSet<>();
private String sha256; //when read from/written to file.
private String sourceLocation; //when read from file
private final boolean rootNode;
private final Map dependencyNameToSha256 = new HashMap<>();
private transient boolean lockedSourceRead = false; //phase 1
private transient boolean lockedDefintionsMerged = false; //phase 2
private transient boolean lockedAnalyzed = false; //phase 3
private void failIfLockRead() {
if (isLockedSourceRead()) {
throw new IllegalStateException("Attempting to modify 'source read' content after source read is locked");
}
}
private void failIfDefintionsMerged() {
lockSourceRead();
if (isLockedDefintionsMerged()) {
throw new IllegalStateException("Attempting to modify 'definition merge' content after definition merge is locked");
}
}
private void failIfLockedAnalyzed() {
lockDefintionsMerged();
if (isLockedAnalyzed()) {
throw new IllegalStateException("Attempting to modify analyzed structure after structure has been computed");
}
}
/**
* Is this node marked as a root node, meaning noone can depend upon it.
*
* @return true if this is a root node, and no other nodes may depend on it.
*/
public boolean isRootNode() {
return rootNode;
}
private void setDepenendencyArrayIfNull() {
if (dependencies == null) {
dependencies = new ArrayList<>();
}
}
public List getDependencies() {
setDepenendencyArrayIfNull();
lockDefintionsMerged();
return Collections.unmodifiableList(dependencies);
}
public DefinitionModel(String name) {
this(name, false);
}
public DefinitionModel(String name, boolean rootNode) {
super(name);
this.rootNode = rootNode;
}
public DefinitionModel(TypeElement type) {
this(type, false);
}
public DefinitionModel(TypeElement type, boolean rootNode) {
super(type);
this.rootNode = rootNode;
}
public void addDependency(DefinitionModel model) {
setDepenendencyArrayIfNull();
failIfDefintionsMerged();
this.dependencies.add(model);
}
public void addDependencies(List model) {
setDepenendencyArrayIfNull();
failIfDefintionsMerged();
this.dependencies.addAll(model);
}
public void addDefinition(InstanceModel model) {
failIfLockRead();
this.objectDefinitions.add(model);
}
public void addDefinition(ExpectedModel model) {
failIfLockRead();
this.expectedDefinitions.add(model);
}
public void addDependencyNames(List model) {
failIfLockRead();
this.dependencyNames.addAll(model);
}
public void addDependencyNames(String dependencyName) {
failIfLockRead();
this.dependencyNames.add(dependencyName);
}
public List getDependencyNames() {
lockSourceRead();
return Collections.unmodifiableList(dependencyNames);
}
public List getObjectDefinitions() {
lockSourceRead();
return Collections.unmodifiableList(objectDefinitions);
}
public List getExpectedDefinitions() {
lockSourceRead();
return Collections.unmodifiableList(expectedDefinitions);
}
public boolean isComplete() {
return getExpectedDefinitions().size() == 0;
}
public List getProvidedInstances() {
lockAnalyzed();
return Collections.unmodifiableList(providedInstances);
}
public void addAllProvidedInstances(Collection providedInstances) {
failIfLockedAnalyzed();
this.providedInstances.addAll(providedInstances);
}
public Set getComputedExpected() {
lockAnalyzed();
return Collections.unmodifiableSet(computedExpected);
}
public void addAllComputedExpected(Collection computedExpected) {
failIfLockedAnalyzed();
this.computedExpected.addAll(computedExpected);
}
public void addComputedExpected(ExpectedModel computedExpected) {
failIfLockedAnalyzed();
this.computedExpected.add(computedExpected);
}
/**
* For the purposes of identification of the object definition class, the location of the class suffices.
*
* @return a unique identity representing this definition, specifically the fully qualified name of the source type.
*/
public String getIdentity() {
//wont lockSourceRead(); as identity is read while attaching definitions.
return getElementLocation();
}
/**
* For the purposes of identification of the object definition class, the location of the class suffices.
*
* @return the Identity of the {@link DefinitionModel}
*/
public String toString() {
lockSourceRead();
return getElementLocation();
}
public String getSha256() {
lockAnalyzed();
return sha256;
}
public void setSha256(String sha256) {
failIfLockedAnalyzed();
lockAnalyzed();
this.sha256 = sha256;
}
public boolean isLockedSourceRead() {
return lockedSourceRead;
}
public boolean isLockedDefintionsMerged() {
return lockedDefintionsMerged;
}
public boolean isLockedAnalyzed() {
return lockedAnalyzed;
}
private void lockSourceRead() {
lockedSourceRead = true;
}
private void lockDefintionsMerged() {
lockSourceRead();
lockedDefintionsMerged = true;
}
/**
* Public so that once all shas are write to {@link DefinitionModel#addDependencyNameToSha256} this
* can be called, locking down the definition.
*/
private void lockAnalyzed() {
lockSourceRead();
lockDefintionsMerged();
lockedAnalyzed = true;
}
public Map getDependencyNameToSha256() {
lockDefintionsMerged();
return Collections.unmodifiableMap(dependencyNameToSha256);
}
public void addDependencyNameToSha256(String dependencyName, String sha256) {
failIfLockedAnalyzed();
dependencyNameToSha256.put(dependencyName, sha256);
}
public void addAllDependencyNameToSha256(Map dependencyNameToSha256) {
failIfLockedAnalyzed();
dependencyNameToSha256.putAll(dependencyNameToSha256);
}
public String getSourceLocation() {
return sourceLocation;
}
public void setSourceLocation(String sourceLocation) {
failIfLockRead();
this.sourceLocation = sourceLocation;
}
public String getSourcePackage() {
String packageName = "";
if (getIdentity().lastIndexOf(".") != -1) {
packageName = getIdentity().substring(0, getIdentity().lastIndexOf("."));
}
return packageName;
}
public String getSourceClass() {
return getIdentity().substring(getIdentity().lastIndexOf(".") + 1);
}
}