001package org.cpsolver.instructor.model; 002 003/** 004 * Attributes of an instructor. Each instructor can have a number of attributes and there are attribute preferences on teaching requests. 005 * Each attribute has an id, a name and a {@link Type}. 006 * 007 * @version IFS 1.3 (Instructor Sectioning)<br> 008 * Copyright (C) 2016 Tomáš Müller<br> 009 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 010 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 011 * <br> 012 * This library is free software; you can redistribute it and/or modify 013 * it under the terms of the GNU Lesser General Public License as 014 * published by the Free Software Foundation; either version 3 of the 015 * License, or (at your option) any later version. <br> 016 * <br> 017 * This library is distributed in the hope that it will be useful, but 018 * WITHOUT ANY WARRANTY; without even the implied warranty of 019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 020 * Lesser General Public License for more details. <br> 021 * <br> 022 * You should have received a copy of the GNU Lesser General Public 023 * License along with this library; if not see 024 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 025 */ 026public class Attribute { 027 private Long iAttributeId; 028 private String iAttributeName; 029 private Type iType; 030 private Attribute iParentAttribute; 031 032 /** 033 * Constructor 034 * @param attributeId attribute id 035 * @param attributeName attribute name 036 * @param type attribute type 037 */ 038 public Attribute(long attributeId, String attributeName, Type type) { 039 iAttributeId = attributeId; 040 iAttributeName = attributeName; 041 iType = type; 042 } 043 044 /** 045 * Attribute id that was provided in the constructor 046 * @return attribute id 047 */ 048 public Long getAttributeId() { return iAttributeId; } 049 050 /** 051 * Attribute name that was provided in the constructor 052 * @return attribute name 053 */ 054 public String getAttributeName() { return iAttributeName == null ? "A" + iAttributeId : iAttributeName; } 055 056 /** 057 * Attribute type that was provided in the constructor 058 * @return attribute type 059 */ 060 public Type getType() { return iType; } 061 062 /** 063 * Parent attribute 064 */ 065 public Attribute getParentAttribute() { return iParentAttribute; } 066 067 /** 068 * Parent attribute 069 */ 070 public void setParentAttribute(Attribute parent) { iParentAttribute = parent; } 071 072 @Override 073 public int hashCode() { 074 return (getAttributeId() == null ? getAttributeName().hashCode() : getAttributeId().hashCode()); 075 } 076 077 @Override 078 public boolean equals(Object o) { 079 if (o == null || !(o instanceof Attribute)) return false; 080 Attribute a = (Attribute)o; 081 return getAttributeId() == null ? getAttributeName().equals(a.getAttributeName()) : getAttributeId().equals(a.getAttributeId()); 082 } 083 084 @Override 085 public String toString() { return getAttributeName() + " (" + getType() + ")"; } 086 087 /** 088 * Attribute type. Each type has an id and a name. It can also define whether attributes of this type are required and/or conjunctive. 089 * If an attribute is required, this means that only instructors that have the attribute can be used, even if it is only preferred. This 090 * allows to put different preferences on multiple attribute that are required. 091 * If a teaching requests require two attributes that are of the same type which is conjunctive, only instructors that have BOTH attributes can be used. 092 * It the type is disjunctive (not conjunctive), it is sufficient for the instructor to have one of the two required attributes. 093 */ 094 public static class Type { 095 private Long iTypeId; 096 private String iTypeName; 097 private boolean iRequired; 098 private boolean iConjunctive; 099 100 /** 101 * Constructor 102 * @param typeId attribute type id 103 * @param typeName attribute type name 104 * @param conjunctive is attribute type conjunctive (if two attributes are required a student must have both). 105 * @param required 106 */ 107 public Type(long typeId, String typeName, boolean conjunctive, boolean required) { 108 iTypeId = typeId; 109 iTypeName = typeName; 110 iConjunctive = conjunctive; 111 iRequired = required; 112 } 113 114 /** 115 * Attribute type id that was provided in the constructor 116 * @return attribute type id 117 */ 118 public Long getTypeId() { return iTypeId; } 119 120 /** 121 * Attribute type name that was provided in the constructor 122 * @return attribute type name 123 */ 124 public String getTypeName() { return iTypeName == null ? "T" + iTypeId : iTypeName; } 125 126 /** 127 * If an attribute is required, this means that only instructors that have the attribute can be used, even if it is only preferred. This 128 * allows to put different preferences on multiple attribute that are required. 129 * @return true if this attribute type is required 130 */ 131 public boolean isRequired() { return iRequired; } 132 133 /** 134 * If a teaching requests require two attributes that are of the same type which is conjunctive, only instructors that have BOTH attributes can be used. 135 * It the type is disjunctive (not conjunctive), it is sufficient for the instructor to have one of the two required attributes. 136 * @return true if this attribute type is conjunctive, false if disjunctive 137 */ 138 public boolean isConjunctive() { return iConjunctive; } 139 140 @Override 141 public int hashCode() { 142 return getTypeId() == null ? getTypeName().hashCode() : getTypeId().hashCode(); 143 } 144 145 @Override 146 public boolean equals(Object o) { 147 if (o == null || !(o instanceof Type)) return false; 148 Type t = (Type)o; 149 return getTypeId() == null ? getTypeName().equals(t.getTypeName()) : getTypeId().equals(t.getTypeId()); 150 } 151 152 @Override 153 public String toString() { return getTypeName(); } 154 } 155 156}