swim.runtime.agent.AgentClass Maven / Gradle / Ivy
// Copyright 2015-2019 SWIM.AI inc.
//
// 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 swim.runtime.agent;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import swim.api.SwimLane;
import swim.api.SwimResident;
import swim.api.SwimTransient;
import swim.api.agent.AbstractAgentType;
import swim.api.agent.Agent;
import swim.api.agent.AgentContext;
import swim.api.agent.AgentException;
import swim.api.lane.CommandLane;
import swim.api.lane.DemandLane;
import swim.api.lane.DemandMapLane;
import swim.api.lane.JoinMapLane;
import swim.api.lane.JoinValueLane;
import swim.api.lane.Lane;
import swim.api.lane.ListLane;
import swim.api.lane.MapLane;
import swim.api.lane.SpatialLane;
import swim.api.lane.SupplyLane;
import swim.api.lane.ValueLane;
import swim.collections.HashTrieMap;
import swim.runtime.lane.CommandLaneView;
import swim.runtime.lane.DemandLaneView;
import swim.runtime.lane.DemandMapLaneView;
import swim.runtime.lane.JoinMapLaneView;
import swim.runtime.lane.JoinValueLaneView;
import swim.runtime.lane.ListLaneView;
import swim.runtime.lane.MapLaneView;
import swim.runtime.lane.SpatialLaneView;
import swim.runtime.lane.SupplyLaneView;
import swim.runtime.lane.ValueLaneView;
import swim.structure.Form;
import swim.structure.Record;
import swim.structure.Value;
import swim.uri.Uri;
public abstract class AgentClass extends AbstractAgentType {
final Class extends A> agentType;
final Constructor extends A> constructor;
AgentClass(Class extends A> agentType, Constructor extends A> constructor) {
this.agentType = agentType;
this.constructor = constructor;
constructor.setAccessible(true);
}
@Override
public Class extends A> type() {
return this.agentType;
}
@Override
public Value props(Uri nodeUri) {
final HashTrieMap params = route().unapply(nodeUri);
final Record props = Record.of();
for (HashTrieMap.Entry param : params) {
props.slot(param.getKey(), param.getValue());
}
return props;
}
@Override
public abstract A createAgent(AgentContext agentContext);
public static AgentClass apply(Class extends A> agentType) {
try {
return new ContextConstructor(agentType, agentType.getDeclaredConstructor(AgentContext.class));
} catch (NoSuchMethodException e) {
try {
return new NoArgConstructor(agentType, agentType.getDeclaredConstructor());
} catch (NoSuchMethodException cause) {
throw new AgentException(cause);
}
}
}
static void reflectLaneFields(Class> agentType, AgentContext agentContext, Agent agent) {
if (agentType != null) {
reflectLaneFields(agentType.getSuperclass(), agentContext, agent);
final Field[] fields = agentType.getDeclaredFields();
for (Field field : fields) {
if (Lane.class.isAssignableFrom(field.getType())) {
field.setAccessible(true);
reflectLaneField(field, agentContext, agent);
}
}
}
}
static void reflectLaneField(Field field, AgentContext agentContext, Agent agent) {
final SwimLane swimLane = field.getAnnotation(SwimLane.class);
if (swimLane != null) {
final Lane lane = reflectLaneType(agent, field, field.getGenericType());
final Uri laneUri = Uri.parse(swimLane.value());
agentContext.openLane(laneUri, lane);
}
}
static Lane reflectLaneType(Agent agent, Field field, Type type) {
if (type instanceof ParameterizedType) {
return reflectParameterizedLaneType(agent, field, (ParameterizedType) type);
}
return reflectOtherLaneType(agent, field, type);
}
static Lane reflectParameterizedLaneType(Agent agent, Field field, ParameterizedType type) {
final Type rawType = type.getRawType();
if (rawType instanceof Class>) {
return reflectLaneTypeArguments(agent, field, (Class>) rawType, type.getActualTypeArguments());
}
return reflectOtherLaneType(agent, field, type);
}
static Lane reflectLaneTypeArguments(Agent agent, Field field, Class> type, Type[] arguments) {
if (CommandLane.class.equals(type)) {
return reflectCommandLaneType(agent, field, type, arguments);
} else if (DemandLane.class.equals(type)) {
return reflectDemandLaneType(agent, field, type, arguments);
} else if (DemandMapLane.class.equals(type)) {
return reflectDemandMapLaneType(agent, field, type, arguments);
} else if (JoinMapLane.class.equals(type)) {
return reflectJoinMapLaneType(agent, field, type, arguments);
} else if (JoinValueLane.class.equals(type)) {
return reflectJoinValueLaneType(agent, field, type, arguments);
} else if (ListLane.class.equals(type)) {
return reflectListLaneType(agent, field, type, arguments);
} else if (MapLane.class.equals(type)) {
return reflectMapLaneType(agent, field, type, arguments);
} else if (SpatialLane.class.equals(type)) {
return reflectSpatialLaneType(agent, field, type, arguments);
} else if (SupplyLane.class.equals(type)) {
return reflectSupplyLaneType(agent, field, type, arguments);
} else if (ValueLane.class.equals(type)) {
return reflectValueLaneType(agent, field, type, arguments);
}
return reflectOtherLaneType(agent, field, type);
}
@SuppressWarnings("unchecked")
static Lane reflectCommandLaneType(Agent agent, Field field, Class> type, Type[] arguments) {
try {
Object object = field.get(agent);
if (object == null) {
object = agent.agentContext().commandLane();
field.set(agent, object);
}
if (object instanceof CommandLaneView>) {
final CommandLaneView
© 2015 - 2025 Weber Informatics LLC | Privacy Policy