/*
 * Copyright 2007 Kickmogu Co. Ltd. All rights reserved.
 *
 * 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.
 */



/* * 作成日: 2006/12/19
 *
 */
package com.kickmogu.rhythm.core;

import com.kickmogu.s2.DAOSequence;
import java.util.*;

import org.apache.commons.lang.StringUtils;

public class Role extends PermissionTarget {
	
	private List<AssignPermission> assisnPermissions = new ArrayList<AssignPermission>();
	
	/**
	 * 権限の追加
	 * @param permCode
	 * @param targetId
	 */
	public AssignPermission assignPermission(String permCode, int targetId) throws ClassNotFoundException {
		Permission perm = Permission.searchByCode(permCode);
		Class rTreeClass = Class.forName(perm.getClassName());
		PermissionTarget target = (PermissionTarget) RhythmTreeManager.getRoot(rTreeClass).search(targetId);
		AssignPermission ap = new AssignPermission(DAOSequence.getNextId(AssignPermission.UNIQ_KEYNAME));
		ap.setPermissionId(perm.getId());
		ap.setTargetId(target.getId());
		assisnPermissions.add(ap);
		return ap;
	}
	
	private boolean isIncludePermissionTarget(PermissionTarget newTarget, List<PermissionTarget> results) {
		for (int i = 0; i < results.size(); i++) {
			if (results.get(i).search(newTarget.getId()) != null) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * このRole配下で指定されたPermissionCodeをもつPermissionTargetを返す。
	 * @param permCode
	 * @return
	 * @throws Exception
	 */
	public List<PermissionTarget> getAssignTarget(String permCode) throws Exception {
		List<PermissionTarget> results = new ArrayList<PermissionTarget>();
		for (int i = 0; i < assisnPermissions.size(); i++) {
			if (assisnPermissions.get(i).getPermission().isIncludePermission(permCode)) {
				PermissionTarget src = assisnPermissions.get(i).getTarget();
				PermissionTarget target = (PermissionTarget) RhythmTreeManager.getRoot(src.getClass()).search(src.getId());
				results.add(target);
			}
		}
		for (int i = 0; i < getChildren().size(); i++) {
			List<PermissionTarget> childResults = ((Role) getChildren().get(i)).getAssignTarget(permCode);
			for (int j = 0; j < childResults.size(); j++) {
				if (!isIncludePermissionTarget(childResults.get(i), results)) {
					PermissionTarget target = (PermissionTarget) RhythmTreeManager.getRoot(childResults.get(i).getClass()).search(childResults.get(i).getId());
					results.add(target);
				}
			}
		}
		return results;
	}

	public void removePermission(int id) {
		assisnPermissions.remove(new AssignPermission(id));
	}
	
	public void updatePermission(int id, String permCode, int targetId) throws ClassNotFoundException {
		AssignPermission newAp = new AssignPermission(id);
		int idx = assisnPermissions.indexOf(newAp);
		if (idx == -1) {
			log.error("update AssignPermission not found:" + id + "," + permCode + "," + targetId);
			return;
		}
		Permission perm = Permission.searchByCode(permCode);
		Class rTreeClass = Class.forName(perm.getClassName());
		PermissionTarget target = (PermissionTarget) RhythmTreeManager.getRoot(rTreeClass).search(targetId);
		newAp.setPermissionId(perm.getId());
		newAp.setTargetId(target.getId());
		assisnPermissions.set(idx, newAp);
	}
	
	/**
	 * @return XML表記の返却
	 */
	public String toXmlAllWithPermission() {
		StringBuffer out = new StringBuffer();
		int level = getLevel();
		out.append(StringUtils.repeat("  ", level - 1));
		out.append(getXmlOpenTagWithPermission());
		
		for (int i = 0; i < getChildren().size(); i++) {
			out.append(((Role) getChildren().get(i)).toXmlAllWithPermission());
		}
		out.append(StringUtils.repeat("  ", level - 1) + getXmlCloseTag());
		return out.toString();
	}

	protected String getXmlOpenTagWithPermission() {
		StringBuffer out = new StringBuffer();
		out.append(getXmlOpenTag());
		for (int i = 0; i < assisnPermissions.size(); i++) {
			out.append(StringUtils.repeat("  ", getLevel() - 2) + " ");
			out.append("<com_kickmogu_rhythm_core_AssignPermission "
					+ "id=\"" + assisnPermissions.get(i).getId() + "\" "
					+ "permissionCode=\"" + assisnPermissions.get(i).getPermission().getCode() 
					+ "\" permissionName=\"" + assisnPermissions.get(i).getPermission().getName() 
					+ "\" permissionClassName=\"" + assisnPermissions.get(i).getPermission().getClassName() 
					+ "\" targetId=\"" + assisnPermissions.get(i).getTarget().getId() 
					+ "\" targetName=\"" + assisnPermissions.get(i).getTarget().getName() + "\"/>");
			out.append("\n");
		}
		return out.toString();
	}
	
	public String toString() {
		StringBuffer out = new StringBuffer();
		out.append(super.toString());
		for (int i = 0; i < assisnPermissions.size(); i++) {
			out.append(StringUtils.repeat("\t", getLevel() - 1));
			
			out.append(i < assisnPermissions.size() - 1 ? "├" : "└");
			out.append(assisnPermissions.get(i).getPermission().getCode() + "->" + assisnPermissions.get(i).getTarget().getName());
			out.append("\n");
		}
		return out.toString();
	}
	
	public static void main(String[] arg) throws Exception {
		Role rootRole = new Role();
		rootRole.setName("全てのユーザ");
		RhythmTreeManager.setRoot(rootRole);
		RhythmTreeManager.write(Role.class);
	}

	public List<AssignPermission> getAssisnPermissions() {
		return assisnPermissions;
	}

	public void setAssisnPermissions(List<AssignPermission> assisnPermissions) {
		this.assisnPermissions = assisnPermissions;
	}
}
