/*
* Copyright 2007 The Fornax Project Team, including the original
* author or authors.
*
* 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
*
* 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.sculptor.generator.util;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import sculptormetamodel.Consumer;
import sculptormetamodel.DomainObject;
import sculptormetamodel.DomainObjectTypedElement;
import sculptormetamodel.Module;
import sculptormetamodel.Parameter;
import sculptormetamodel.Reference;
import sculptormetamodel.Repository;
import sculptormetamodel.RepositoryOperation;
import sculptormetamodel.Service;
import sculptormetamodel.ServiceOperation;
/**
* This class checks circular dependency constraints between Modules.
*
*/
public class DependencyConstraints {
public static boolean checkCyclicDependencies(Module module) {
Set<Module> dependencies = new HashSet<Module>();
collectDependencies(module, dependencies);
boolean cycleFound = dependencies.contains(module);
return !cycleFound;
}
public static List<Module> getModulesDependingOn(Module module) {
Set<Module> result = new HashSet<Module>();
List<Module> all = module.getApplication().getModules();
for (Module each : all) {
if (each == module) {
result.add(each);
} else {
Set<Module> dependencies = new HashSet<Module>();
collectDependencies(each, dependencies);
if (dependencies.contains(module)) {
result.add(each);
}
}
}
return new ArrayList<Module>(result);
}
static void collectDependencies(Module module, Set<Module> dependencies) {
List<DomainObject> domainObjects = module.getDomainObjects();
for (DomainObject d : domainObjects) {
addDependencies(module, d, dependencies);
}
List<Service> services = module.getServices();
for (Service s : services) {
addDependencies(module, s, dependencies);
}
List<Consumer> consumers = module.getConsumers();
for (Consumer c : consumers) {
addDependencies(module, c, dependencies);
}
}
private static void addDependencies(Module fromModule, Service service, Set<Module> dependencies) {
for (Service delegate : delegateServices(service)) {
Module m = delegate.getModule();
addDependency(fromModule, m, dependencies);
}
List<ServiceOperation> operations = service.getOperations();
for (ServiceOperation op : operations) {
addDependency(fromModule, op, dependencies);
}
}
private static void addDependencies(Module fromModule, Consumer consumer, Set<Module> dependencies) {
for (Service delegate : (List<Service>) consumer.getServiceDependencies()) {
Module m = delegate.getModule();
addDependency(fromModule, m, dependencies);
}
}
private static void addDependencies(Module fromModule, DomainObject domainObject, Set<Module> dependencies) {
if (domainObject.getExtends() != null) {
Module m = domainObject.getExtends().getModule();
addDependency(fromModule, m, dependencies);
}
List<Reference> references = domainObject.getReferences();
for (Reference r : references) {
addDependencies(fromModule, r, dependencies);
}
if (domainObject.getRepository() != null) {
addDependency(fromModule, domainObject.getRepository(), dependencies);
}
}
private static void addDependency(Module fromModule, Repository repository, Set<Module> dependencies) {
List<RepositoryOperation> operations = repository.getOperations();
for (RepositoryOperation op : operations) {
addDependency(fromModule, op, dependencies);
}
}
private static void addDependencies(Module fromModule, Reference ref, Set<Module> dependencies) {
if (ref.getTo() == null) {
return;
}
Module m = ref.getTo().getModule();
addDependency(fromModule, m, dependencies);
}
private static void addDependency(Module fromModule, ServiceOperation op, Set<Module> dependencies) {
addDependency(fromModule, (DomainObjectTypedElement) op, dependencies);
List<Parameter> parameters = op.getParameters();
for (Parameter p : parameters) {
addDependency(fromModule, p, dependencies);
}
}
private static void addDependency(Module fromModule, DomainObjectTypedElement type, Set<Module> dependencies) {
DomainObject to = type.getDomainObjectType();
if (to != null) {
addDependency(fromModule, to.getModule(), dependencies);
}
}
private static void addDependency(Module fromModule, Module toModule, Set<Module> dependencies) {
if (!toModule.equals(fromModule)) {
if (dependencies.add(toModule)) {
// recursive call, when m not used before
collectDependencies(toModule, dependencies);
}
}
}
private static Set<Service> delegateServices(Service service) {
Set<Service> dependencies = new HashSet<Service>();
List<ServiceOperation> operations = service.getOperations();
for (ServiceOperation op : operations) {
if (op.getServiceDelegate() != null) {
dependencies.add(op.getServiceDelegate().getService());
}
}
return dependencies;
}
}