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