Skip to content

Commit

Permalink
Merge pull request #123 from d3scomp/newgen-keznikl
Browse files Browse the repository at this point in the history
	A few updates on how KnowledgeNotFoundException is constructed and reacted to in tasks
  • Loading branch information
mkit committed Dec 4, 2013
2 parents fe923d5 + c4f357b commit cad43ef
Show file tree
Hide file tree
Showing 8 changed files with 353 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,18 @@ public class AnnotationProcessor {
put(Out.class, ParameterDirection.OUT);
}
});
private RuntimeMetadataFactory factory;
private RuntimeMetadata model;
protected RuntimeMetadataFactory factory;


/**
* Initializes the processor with the given model factory.
* All the model elements produced by the processor will be created via this factory.
*/
public AnnotationProcessor(RuntimeMetadataFactory factory) {
this.factory = factory;
}

private void setModel(RuntimeMetadata model) throws AnnotationProcessorException {
if (model == null) {
throw new AnnotationProcessorException("Provided model cannot be null.");
}
this.model = model;
}


/**
* Processing of a single file.
Expand All @@ -70,8 +69,7 @@ private void setModel(RuntimeMetadata model) throws AnnotationProcessorException
* @throws AnnotationProcessorException
*/
public void process(RuntimeMetadata model, Object obj) throws AnnotationProcessorException {
setModel(model);
processObject(obj);
processObject(model, obj);
}

/**
Expand All @@ -86,10 +84,9 @@ public void process(RuntimeMetadata model, Object obj) throws AnnotationProcesso
* @throws AnnotationProcessorException
*/
public void process(RuntimeMetadata model, Object obj, Object... objs) throws AnnotationProcessorException {
setModel(model);
processObject(obj);
processObject(model, obj);
for (Object o: objs) {
processObject(o);
processObject(model, o);
}
}

Expand All @@ -103,15 +100,14 @@ public void process(RuntimeMetadata model, Object obj, Object... objs) throws An
* @throws AnnotationProcessorException
*/
public void process(RuntimeMetadata model, List<Object> objs) throws AnnotationProcessorException {
setModel(model);
if (objs == null) {
throw new AnnotationProcessorException("Provide an initialized object or a non-empty list of objects.");
}
if (objs.isEmpty()) {
throw new AnnotationProcessorException("Cannot process an empty list.");
}
for (Object o: objs) {
processObject(o);
processObject(model, o);
}
}

Expand All @@ -125,10 +121,14 @@ public void process(RuntimeMetadata model, List<Object> objs) throws AnnotationP
* @param obj
* object to be processed
*/
void processObject(Object obj) throws AnnotationProcessorException {
void processObject(RuntimeMetadata model, Object obj) throws AnnotationProcessorException {
if (model == null) {
throw new AnnotationProcessorException("Provided model cannot be null.");
}
if (obj == null) {
throw new AnnotationProcessorException("Provided object(s) cannot be null.");
}

boolean isClass = (obj instanceof Class<?>);
Class<?> clazz = (isClass) ? (Class<?>) obj : obj.getClass();
boolean isC = isComponentDefinition(clazz);
Expand All @@ -138,39 +138,71 @@ void processObject(Object obj) throws AnnotationProcessorException {
"Class: " + clazz.getCanonicalName() +
"->Both @" + Component.class.getSimpleName() + " or @" + Ensemble.class.getSimpleName() + " annotation found.");
}
if (isC) {
if (isClass) {
throw new AnnotationProcessorException(
"For a component to be parsed, it has to be an INSTANCE of a class annotated with @"
+ Component.class.getSimpleName() + ".");
}
ComponentInstance ci = createComponentInstance(obj);
model.getComponentInstances().add(ci);
// Create ensemble controllers for all the already-processed ensemble definitions
for (EnsembleDefinition ed: model.getEnsembleDefinitions()) {
EnsembleController ec = factory.createEnsembleController();
ec.setComponentInstance(ci);
ec.setEnsembleDefinition(ed);
ci.getEnsembleControllers().add(ec);
}
if (isC) {
processComponentInstance(model, obj);
return;
}
if (isE) {
EnsembleDefinition ed = createEnsembleDefinition(clazz);
model.getEnsembleDefinitions().add(ed);
// Create ensemble controllers for all the already-processed component instance definitions
for (ComponentInstance ci: model.getComponentInstances()) {
EnsembleController ec = factory.createEnsembleController();
ec.setComponentInstance(ci);
ec.setEnsembleDefinition(ed);
ci.getEnsembleControllers().add(ec);
}

model.getEnsembleDefinitions().add(ed);

return;
}
throw new AnnotationProcessorException(
"Class: " + clazz.getCanonicalName() +
"->No @" + Component.class.getSimpleName() + " or @" + Ensemble.class.getSimpleName() + " annotation found.");
}

/**
* Checks if the object is annotated as @{@link Component} and calls the respective creator.
* It also creates the appropriate {@link EnsembleController}s for the {@link EnsembleDefinition}s in the model.
* The parsed {@link ComponentInstance} is automatically added to the model.
*
* @param model the model to which the instance is to be added
* @param obj instance definition to be processed
* @return the parsed {@link ComponentInstance}
* @throws AnnotationProcessorException if the instance definition object is invalid
*/
public ComponentInstance processComponentInstance(RuntimeMetadata model, Object obj) throws AnnotationProcessorException {
if (model == null) {
throw new AnnotationProcessorException("Provided model cannot be null.");
}
if (obj == null) {
throw new AnnotationProcessorException("Provided object(s) cannot be null.");
}

boolean isClass = (obj instanceof Class<?>);
Class<?> clazz = (isClass) ? (Class<?>) obj : obj.getClass();
boolean isC = isComponentDefinition(clazz);

// TODO: unify the checks (in processObject the presence of multiple annotations is checked)
if (!isC || isClass) {
throw new AnnotationProcessorException(
"For a component to be parsed, it has to be an INSTANCE of a class annotated with @"
+ Component.class.getSimpleName() + ".");
}

ComponentInstance ci = createComponentInstance(obj);
// Create ensemble controllers for all the already-processed ensemble definitions
for (EnsembleDefinition ed: model.getEnsembleDefinitions()) {
EnsembleController ec = factory.createEnsembleController();
ec.setComponentInstance(ci);
ec.setEnsembleDefinition(ed);
ci.getEnsembleControllers().add(ec);
}

model.getComponentInstances().add(ci);

return ci;
}

/**
* Creator of a single correctly-initialized {@link ComponentInstance} object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import cz.cuni.mff.d3s.deeco.logging.Log;
import cz.cuni.mff.d3s.deeco.model.runtime.api.KnowledgeChangeTrigger;
import cz.cuni.mff.d3s.deeco.model.runtime.api.KnowledgePath;
import cz.cuni.mff.d3s.deeco.model.runtime.api.PathNode;
import cz.cuni.mff.d3s.deeco.model.runtime.api.PathNodeComponentId;
import cz.cuni.mff.d3s.deeco.model.runtime.api.PathNodeField;
import cz.cuni.mff.d3s.deeco.model.runtime.api.Trigger;

Expand Down Expand Up @@ -56,7 +58,11 @@ public ValueSet get(Collection<KnowledgePath> knowledgePaths)
ValueSet result = new ValueSet();
Object value;
for (KnowledgePath kp : knowledgePaths) {
value = getKnowledge(kp.getNodes());
try {
value = getKnowledge(kp.getNodes());
} catch (KnowledgeNotFoundException knfe) {
throw new KnowledgeNotFoundException(kp);
}
if (knowledge.equals(value))
for (KnowledgePath rootKP : knowledge.keySet())
result.setValue(rootKP, knowledge.get(rootKP));
Expand Down Expand Up @@ -102,10 +108,9 @@ public void register(Trigger trigger,
public void unregister(Trigger trigger,
TriggerListener triggerListener) {
if (trigger instanceof KnowledgeChangeTrigger) {
KnowledgePath kp = ((KnowledgeChangeTrigger) trigger)
.getKnowledgePath();
if (knowledgeChangeListeners.containsKey(kp)) {
knowledgeChangeListeners.get(kp).remove(triggerListener);
KnowledgeChangeTrigger kt = ((KnowledgeChangeTrigger) trigger);
if (knowledgeChangeListeners.containsKey(kt)) {
knowledgeChangeListeners.get(kt).remove(triggerListener);
}
}
}
Expand Down Expand Up @@ -143,12 +148,22 @@ public boolean equals(Object that) {
return ((BaseKnowledgeManager) that).id.equals(id);
return false;
}

@Override
public int hashCode() {
return id.hashCode();
}

protected Object getKnowledge(List<PathNode> knowledgePath)
throws KnowledgeNotFoundException {
assert (knowledgePath != null);
if (knowledgePath.isEmpty())
return knowledge;

// handle ID separately
if ((knowledgePath.size() == 1) && (knowledgePath.get(0) instanceof PathNodeComponentId))
return id;

int containmentEndIndex;
for (KnowledgePath kp : knowledge.keySet()) {
try {
Expand Down Expand Up @@ -284,10 +299,11 @@ private void deleteKnowledge(Collection<KnowledgePath> knowledgePaths) {
continue;
}
}
for (Object p : parentsToDeleteKeys.keySet()) {
keysToDelete = parentsToDeleteKeys.get(p);
for (Entry<Object, List<String>> entry : parentsToDeleteKeys.entrySet()) {
Object p = entry.getKey();
keysToDelete = entry.getValue();
// We need to sort the keys in order to start deleting from the end.
// This is important for list consitency.
// This is important for list consistency.
Collections.sort(keysToDelete);
for (int i = keysToDelete.size() - 1; i >= 0; i--) {
fieldName = keysToDelete.get(i);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
package cz.cuni.mff.d3s.deeco.knowledge;

import cz.cuni.mff.d3s.deeco.model.runtime.api.KnowledgePath;

/**
* @author Michal Kit <kit@d3s.mff.cuni.cz>
*
*/
public class KnowledgeNotFoundException extends Exception {
private static final long serialVersionUID = -999702030030889941L;

KnowledgePath notFoundPath;

KnowledgeNotFoundException() {}

public KnowledgeNotFoundException(KnowledgePath notFoundPath) {
this.notFoundPath = notFoundPath;
}

public KnowledgePath getNotFoundPath() {
return notFoundPath;
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,13 @@ void init() {
componentInstanceAdded(ci);
}


// register adapters to listen for model changes
// listen to ADD/REMOVE in RuntimeMetadata.getComponentInstances()
Adapter componentInstancesAdapter = new AdapterImpl() {
public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
if (notification.getFeature() == model.getComponentInstances()) {
if (notification.getFeature() == model.eClass().getEStructuralFeature(RuntimeMetadataPackage.RUNTIME_METADATA__COMPONENT_INSTANCES)) {
// new component instance added
if (notification.getEventType() == Notification.ADD) {
componentInstanceAdded((ComponentInstance) notification.getNewValue());
Expand Down Expand Up @@ -235,7 +236,7 @@ void componentInstanceAdded(final ComponentInstance instance) {
Adapter componentInstanceAdapter = new AdapterImpl() {
public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
if (notification.getFeature() == instance.getComponentProcesses()) {
if (notification.getFeature() == instance.eClass().getEStructuralFeature(RuntimeMetadataPackage.COMPONENT_INSTANCE__COMPONENT_PROCESSES)) {
// if new task added
if (notification.getEventType() == Notification.ADD) {
componentProcessAdded(instance, (ComponentProcess) notification.getNewValue());
Expand Down Expand Up @@ -316,7 +317,7 @@ void componentProcessAdded(final ComponentInstance instance,
final Task newTask = new ProcessTask(process, scheduler);
cir.getProcessTasks().put(process, newTask);

componentProcessActiveChanged(process, process.isIsActive());
componentProcessActiveChanged(instance, process, process.isIsActive());

// register adapters to listen for model changes
// listen to change in ComponentProcess.isActive
Expand All @@ -325,7 +326,7 @@ public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
if ((notification.getFeatureID(ComponentProcess.class) == RuntimeMetadataPackage.COMPONENT_PROCESS__IS_ACTIVE)
&& (notification.getEventType() == Notification.SET)){
componentProcessActiveChanged(process, notification.getNewBooleanValue());
componentProcessActiveChanged(instance, process, notification.getNewBooleanValue());
}
}
};
Expand All @@ -347,20 +348,20 @@ public void notifyChanged(Notification notification) {
* @see Scheduler#removeTask(Task)
*
*/
void componentProcessActiveChanged(ComponentProcess process, boolean active) {
void componentProcessActiveChanged(ComponentInstance instance, ComponentProcess process, boolean active) {
if (process == null) {
Log.w("Attempting to to change the activity of a null process.");
return;
}
// the instance is not registered
if ((!componentRecords.containsKey(process.getComponentInstance())
if ((!componentRecords.containsKey(instance)
// OR the process is not registered
|| (!componentRecords.get(process.getComponentInstance()).getProcessTasks().containsKey(process)))) {
|| (!componentRecords.get(instance).getProcessTasks().containsKey(process)))) {
Log.w(String.format("Attempting to change the activity of an unregistered process (%s).", process));
return;
}

Task t = componentRecords.get(process.getComponentInstance()).getProcessTasks().get(process);
Task t = componentRecords.get(instance).getProcessTasks().get(process);

Log.i(String.format("Changing the activity of task %s corresponding to process %s to %s.", t, process, active));

Expand Down Expand Up @@ -456,7 +457,7 @@ void componentProcessRemoved(ComponentInstance instance,
componentProcessAdapters.remove(process);
}

componentProcessActiveChanged(process, false);
componentProcessActiveChanged(instance, process, false);

cir.getProcessTasks().remove(process);
}
Expand Down
Loading

0 comments on commit cad43ef

Please sign in to comment.