⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 contextmodelreader.java

📁 用JAVA实现排序等简单算法的演示
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
					// 从以该动作节点为根的子树查找有关参数的描述,即查找标记为 argument 的元素
					argumentNode = findSubTreeNodeByTagName(node, ContextModelTag.argument);
					while (argumentNode != null) {
						// 找到标记为 argument 的元素,则从它的属性中获取参数名和参数类型,分别作为上下文元信息的名字和类型
						contextName = getAttributeOfElement(argumentNode, ContextModelTag.name);
						contextType = getAttributeOfElement(argumentNode, ContextModelTag.type);
						
						// 添加到事件的上下文元信息列表中
						eventData.addMetaContextData(contextName, contextType);
						// 从兄弟节点开始查找当前动作节点的其他参数描述
						argumentNode = findBrotherNodeByTagName(argumentNode, ContextModelTag.argument);
					}
					
					// 从当前动作节点的儿子节点中获得有关动作实现的信息
					node = findChildNodeByTagName(node, ContextModelTag.implementation);
					// 根据获得的实现信息(即实现该动作的方法名)重新触发事件的域名
					sourceFieldName = getTextOfElement(node);
				}
			}

			eventData.setEventType(eventType);
			
			// 调整触发事件类名和域名。因为动作和数据的实现中支持方法和属性的全名(即包括包、类的名),因此
			// 可能需要从已经得到的域名中提取类名,提取得到的类才是真正触发事件的类
			int fieldIndex = sourceFieldName.lastIndexOf('.');
			if (fieldIndex >= 0) {
				// 这表明在实现域中有类的声明,因此相应的实现类也应该就是这个域中所声明的类
				sourceClassName = sourceFieldName.substring(0, fieldIndex);
				sourceFieldName = sourceFieldName.substring(fieldIndex+1);
			}
			// 设置触发事件的类名和域名
			eventData.setSourceClassName(sourceClassName);
			eventData.setSourceFieldName(sourceFieldName);
			
			// 将事件信息添加到事件信息列表中
			events.addEventData(eventData);
		}
		
		// 设置 eventList 为获得的事件信息列表,以备下次调用本方法时直接返回该对象
		eventList = events;

		return eventList;
	}
	
	/**
	 * 获取模型中所描述的上下文元信息
	 * @throws ContextModelException 当模型描述有错时,可能抛出该类型的异常
	 */
	public ContextList getMetaContextList() throws ContextModelException {
		// 如果已经获取过,则直接返回 metaContextList
		if (metaContextList != null) return metaContextList;
		
		// 因为是从模型所描述的事件信息中获取上下文元信息,因此先获取事件信息列表放到 eventList 中
		getEventList();

		ContextList contextList = new ContextList();
		// 从事件信息列表中提出上下文元信息
		for (int index = 0; index < eventList.getEventSize(); index++) {
			EventData event = eventList.getEventData(index);
			// 上下文名称就是事件名称
			Context context = new Context(event.getEventName());
			for (int rawDataIndex = 0; rawDataIndex < event.getMetaContextNum(); rawDataIndex++) {
				// 上下文元信息就是存放在事件中的上下文元信息
				ContextData rawData = event.getMetaContextData(rawDataIndex);
				context.addContextData(rawData);
			}
			contextList.addContext(context);
		}
		
		// 设置 metaContextList 为获得的上下文元信息,以备下次调用本方法时直接返回该对象
		metaContextList = contextList;

		return metaContextList;
	}
	
	/**
	 * 根据上下文模型,生成从算法实现获取所需上下文的 sensor ,即 AspectJ 文件
	 * @throws ContextModelException 模型有错时抛出该异常
	 * @throws IOException 读写文件有错时抛出该异常
	 */
	public void generateContextSensor() throws ContextModelException, IOException {
		// 因为是根据事件信息来生成 aspect ,因此需要先获取事件列表信息放到 eventList 中
		getEventList();
		
		// sensor 所在的包统一位 contextSensor
		String sensorPackage = "contextSensor";
		// sensor 的名字为算法组名+"Sensor"
		String sensorName = algorithmGroup.getAlgorithmGroupName() + "Sensor";
		// 创建相应的 AspectJ 文件
		PrintWriter out = new PrintWriter(new FileWriter(sensorPackage + "/" + sensorName + ".aj"));

		// 生成定义 aspect 所在包的语句
		out.println("package " + sensorPackage + ";");
		out.println();
		
		// 生成 AspectJ 文件头部的一些语句,这些语句主要是引入该文件所需的类
		generateSensorHead(out);
		
		// 下面开始生成真正的 aspect 声明
		out.println("public aspect " + sensorName + " {");
		for (int eventIndex = 0; eventIndex < eventList.getEventSize(); eventIndex++) {
			EventData event = eventList.getEventData(eventIndex);
			
			// 根据事件列表中的事件信息生成 pointcut 和 advice
			generateSensorPointcut(out, event);
			generateSensorAdvice(out, event);
			out.println();
		}
		out.println("}");
		out.close();
	}
	
	/**
	 * 根据事件信息 event 生成获取与该事件相关的上下文的 pointcut
	 */
	private void generateSensorPointcut(PrintWriter out, EventData event) {
		String indent = "    ";
		StringBuffer result = new StringBuffer(indent);
		
		// 下面根据声明 pointcut 的语法进行生成,pointcut 的名字就是事件名
		result.append("pointcut " + event.getEventName());
		// 根据与事件相关的上下文元信息生成 pointcut 中的参数
		result.append(generateArguments(event) + " : ");
		// 根据触发事件时间参照生成 pointcut 的类型,即 call, set 等 
		result.append(event.getEventRefer());
		if (event.getEventType() == EventData.ACTION_EVENT) {
			// 如果事件与动作相关,则 pointcut 的连接点模式包含参数类型信息
			result.append("(* " + event.getSourceClassName() + "." + event.getSourceFieldName() + generateArgumentTypes(event) + ")");
		} else {
			// 如果事件与数据相关,则 pointcut 的连接点模式不包含参数类型信息
			result.append("(* " + event.getSourceClassName() + "." + event.getSourceFieldName() + ")");
		}
			
		if (event.getMetaContextNum() > 0) {
			// 如果事件确实有上下文元信息,则 pointcut 有参数 
			result.append(" && args" + generateArgumentNames(event) + ";");
		} else result.append(";");
		out.println(result);
	}

	/**
	 * 根据事件信息 event 生成获取与该事件相关的上下文的 advice
	 */
	private void generateSensorAdvice(PrintWriter out, EventData event) {
		String indent = "    ";
		StringBuffer result = new StringBuffer(indent);

		// 根据 advice 的语法生成 advice 的参数信息
		result.append(event.getEventTime() + generateArguments(event) + " : ");
		result.append(event.getEventName() + generateArgumentNames(event) + " {");
		out.println(result);
		// 真正生成 advice 的体
		generateSensorAdviceBody(out, event); 
		out.println(indent + "}");
	}

	/**
	 * 根据事件信息 event 生成获取与该事件相关的上下文的 advice 的体(即花括号以内的内容)
	 * @param out
	 * @param event
	 */
	private void generateSensorAdviceBody(PrintWriter out, EventData event) {
		String indent = "        ";
		// 在 advice 中,首先创建一个上下文 context ,该上下文的名字就是事件的名字
		out.println(indent + "Context context = new Context(\"" + event.getEventName() + "\");");
		
		String name = null;
		String type = null;
		String valueString = null;
		
		// 根据与事件有关的上下文元信息,生成往上下文 context 添加上下文信息(包括名字、类型和值)的语句
		for (int index = 0; index < event.getMetaContextNum(); index++) {
			ContextData rawData = event.getMetaContextData(index);
			name = rawData.getName();
			type = rawData.getType();
			// 根据名字和类型生成取值的语句,主要是因为上下文信息中存放的值必须是对象类型,因此需要根据
			// 类型信息对取值的语句进行调整
			valueString = generateValueString(name, type);
			out.println(indent + "context.addContextData(\"" + name + "\", \"" + type + "\", " + valueString + ");"); 
		}
		
		// 生成往上下文池管理器 CPM 添加上下文信息的语句
		out.println(indent + "CPM.addContext(context);");
	}
	
	/**
	 * 根据要获取的值的参数名 name 与参数类型 type,生成获取值的语句(串)
	 */
	private String generateValueString(String name, String type) {
		final int primitiveTypeNum = 8;
		// 下面列出了 Java 中所使用的基本数据类型及其包装该基本类型所使用的类,以便使用该类创建对应基本数据类型数据的对象
		String[][] typeConverter = { 
				{"boolean", "Boolean"}, {"byte", "Byte"}, {"char", "Character"}, {"double", "Double"}, 
				{"float", "Float"}, {"int", "Integer"}, {"long", "Long"}, {"short", "Short"}
		};
		
		int typeIndex = 0;
		for (typeIndex = 0; typeIndex < primitiveTypeNum; typeIndex++) {
			// 如果参数类型 type 是基本数据类型,则生成创建相应包装类的对象的语句,注意在生成的 aspect 中,
			// 根据 pointcut 和 advice 的语义,真正获得的值就是存放在名为 name 的参数中,因为根据前面生成
			// pointcut 和 advice 的方法,name 就是声明在 pointcut 和 advice 的参数中
			if (type.equals(typeConverter[typeIndex][0])) return "new " + typeConverter[typeIndex][1] + "(" + name + ")";
		}
		
		// 如果不是基本数据类型,即是对象,则直接返回参数名,该参数名将真正获得对应的值(即相应对象的引用)
		return name;
	}
	
	/**
	 * 根据事件信息 event 中存放的上下文元信息生成 pointcut 或 advice 中的参数名列表,注意在 pointcut 或 
	 * advice 中有时需要参数名列表,有时需要参数类型列表,有时需要参数名、参数类型列表。参数名取自上下文元
	 * 信息中的信息名,参数类型取自上下文元信息的信息类型
	 */
	private String generateArgumentNames(EventData event) {
		StringBuffer result = new StringBuffer("(");
		int index = 0;
		int number = event.getMetaContextNum();
		ContextData rawData = null;
		
		if (index < number) {
			rawData = event.getMetaContextData(index);
			result.append(rawData.getName());
		}
		index = index + 1;
		while (index < number) {
			rawData = event.getMetaContextData(index);
			result.append(", " + rawData.getName());
			index = index + 1;
		}
		result.append(")");
		return result.toString();
	}

	/**
	 * 根据事件信息 event 中存放的上下文元信息生成 pointcut 或 advice 中的参数类型列表,注意在 pointcut 或 
	 * advice 中有时需要参数名列表,有时需要参数类型列表,有时需要参数名、参数类型列表。参数名取自上下文元
	 * 信息中的信息名,参数类型取自上下文元信息的信息类型
	 */
	private String generateArgumentTypes(EventData event) {
		StringBuffer result = new StringBuffer("(");
		int index = 0;
		int number = event.getMetaContextNum();
		ContextData rawData = null;
		
		if (index < number) {
			rawData = event.getMetaContextData(index);
			result.append(rawData.getType());
		}
		index = index + 1;
		while (index < number) {
			rawData = event.getMetaContextData(index);
			result.append(", " + rawData.getType());
			index = index + 1;
		}
		result.append(")");
		return result.toString();
	}

	/**
	 * 根据事件信息 event 中存放的上下文元信息生成 pointcut 或 advice 中的参数列表(包括参数名和参数类型),
	 * 注意在 pointcut 或 advice 中有时需要参数名列表,有时需要参数类型列表,有时需要参数名、参数类型列表。
	 * 参数名取自上下文元信息中的信息名,参数类型取自上下文元信息的信息类型
	 */
	private String generateArguments(EventData event) {
		StringBuffer result = new StringBuffer("(");
		int index = 0;
		int number = event.getMetaContextNum();
		ContextData rawData = null;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -