package simulator;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import models.algebra.Constant;
import models.algebra.Expression;
import models.algebra.Type;
import models.dataConstraintModel.DataConstraintModel;
import models.dataConstraintModel.ResourceHierarchy;
import simulator.states.*;
public class Resource {
private Resource parent = null;
private Map<String, Resource> children = null;
private ResourceHierarchy resourceHierarchy = null;
private ResourceState state = null;
private Constant parameter = null;
public Resource(Resource resource) {
this.resourceHierarchy = resource.resourceHierarchy;
this.parent = resource.parent;
this.state = (ResourceState) resource.state.clone();
this.parameter = resource.parameter;
}
public Resource(ResourceHierarchy resourceHierarchy) {
this.resourceHierarchy = resourceHierarchy;
Type resType = resourceHierarchy.getResourceStateType();
if (resourceHierarchy.getChildren().size() > 0
|| DataConstraintModel.typeList.isAncestorOf(resType)
|| DataConstraintModel.typeMap.isAncestorOf(resType)
|| DataConstraintModel.typeJson.isAncestorOf(resType)) {
if (DataConstraintModel.typeList.isAncestorOf(resType)) {
// List resource
state = new ListResourceState();
} else if (DataConstraintModel.typeMap.isAncestorOf(resType)) {
// Map resource
state = new MapResourceState();
} else {
// Json resource
state = new JsonResourceState();
children = new LinkedHashMap<>();
for (ResourceHierarchy child: resourceHierarchy.getChildren()) {
Resource cRes = new Resource(child, this);
((JsonResourceState) state).addChildState(child.getResourceName(), cRes.getState());
children.put(child.getResourceName(), cRes);
}
}
} else {
Expression initValue = resourceHierarchy.getInitialValue();
if (initValue != null && initValue instanceof Constant) {
state = new PrimitiveResourceState((Constant) resourceHierarchy.getInitialValue());
} else {
state = new PrimitiveResourceState(null);
}
}
}
public Resource(ResourceHierarchy resourceHierarchy, Resource parent) {
this(resourceHierarchy);
this.parent = parent;
}
public Resource(ResourceHierarchy resourceHierarchy, Resource parent, ResourceState state) {
this.resourceHierarchy = resourceHierarchy;
this.parent = parent;
this.state = state;
}
public Resource(ResourceHierarchy resourceHierarchy, Resource parent, Constant parameter, ResourceState state) {
this.resourceHierarchy = resourceHierarchy;
this.parent = parent;
this.parameter = parameter;
this.state = state;
}
public Resource getParent() {
return parent;
}
public void setParent(Resource parent) {
this.parent = parent;
}
public ResourceHierarchy getResourceHierarchy() {
return resourceHierarchy;
}
public ResourceIdentifier getResourceIdentifier() {
ResourceIdentifier resId = null;
if (parent != null) {
ResourceIdentifier parentResId = parent.getResourceIdentifier();
if (resourceHierarchy.getNumParameters() == 0) {
resId = new ResourceIdentifier(parentResId, resourceHierarchy.getResourceName(), resourceHierarchy);
} else {
resId = new ResourceIdentifier(parentResId, parameter, resourceHierarchy);
}
} else {
resId = new ResourceIdentifier(resourceHierarchy.getResourceName(), resourceHierarchy);
}
return resId;
}
public ResourceState getState() {
return state;
}
public void changeState(ResourceState state) {
this.state = state;
}
public Constant getParameter() {
return parameter;
}
public Collection<Resource> getChildren() {
Map<String, Resource> childrenMap = getChildrenMap();
if (childrenMap == null) return null;
return childrenMap.values();
}
public Map<String, Resource> getChildrenMap() {
Map<String, Resource> children = null;
if (resourceHierarchy.getChildren().size() > 0) {
children = new LinkedHashMap<>();
ResourceHierarchy childRes = resourceHierarchy.getChildren().iterator().next();
if (childRes.getNumParameters() > 0) {
// List or Map type.
if (state instanceof CompositeResourceState) {
// If the list or map is not nil.
Map<String, ResourceState> childStates = ((CompositeResourceState) state).getChildStates();
for (Map.Entry<String, ResourceState> childEnt: childStates.entrySet()) {
String childParam = childEnt.getKey();
ResourceState childState = childEnt.getValue();
Type thisType = resourceHierarchy.getResourceStateType();
if (DataConstraintModel.typeList.isAncestorOf(thisType)) {
children.put(childParam, new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeInt), childState));
} else if (DataConstraintModel.typeMap.isAncestorOf(thisType)) {
children.put(childParam, new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState));
}
}
}
} else {
// Json type.
Map<String, ResourceState> childStates = ((CompositeResourceState) state).getChildStates();
if (this.children == null || this.children.size() < childStates.size()) {
for (Map.Entry<String, ResourceState> childEnt: childStates.entrySet()) {
String childParam = childEnt.getKey();
ResourceState childState = childEnt.getValue();
Type thisType = resourceHierarchy.getResourceStateType();
for (ResourceHierarchy c: resourceHierarchy.getChildren()) {
if (c.getResourceName().equals(childParam.replace("\"", ""))) {
childRes = c;
break;
}
}
if (DataConstraintModel.typeJson.isAncestorOf(thisType)) {
children.put(childParam, new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState));
}
}
this.children = children;
}
return this.children;
}
}
return children;
}
public Resource getDescendant(ResourceIdentifier resId) {
if (this.getResourceIdentifier().equals(resId)) return this;
if (!resId.startsWith(this.getResourceIdentifier())) return null;
for (Resource child: getChildren()) {
Resource res = child.getDescendant(resId);
if (res != null) return res;
}
return null;
}
public Resource getDescendant(String resId) {
if (this.getResourceIdentifier().toString().equals(resId)) return this;
if (!resId.startsWith(this.getResourceIdentifier().toString())) return null;
for (Resource child: getChildren()) {
Resource res = child.getDescendant(resId);
if (res != null) return res;
}
return null;
}
}