/*
* CatalogPieceOfFurniture.java 7 avr. 2006
*
* Sweet Home 3D, Copyright (c) 2006 Emmanuel PUYBARET / eTeks <info@eteks.com>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.eteks.sweethome3d.model;
import java.math.BigDecimal;
import java.text.Collator;
/**
* A catalog piece of furniture.
* @author Emmanuel Puybaret
*/
public class CatalogPieceOfFurniture implements Comparable<CatalogPieceOfFurniture>, PieceOfFurniture {
private static final float [][] INDENTITY_ROTATION = new float [][] {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
private final String id;
private final String name;
private final String description;
private final String information;
private final String [] tags;
private final Long creationDate;
private final Float grade;
private final Content icon;
private final Content planIcon;
private final Content model;
private final float width;
private final float depth;
private final float height;
private final boolean proportional;
private final float elevation;
private final boolean movable;
private final boolean doorOrWindow;
private final float [][] modelRotation;
private final String staircaseCutOutShape;
private final String creator;
private final boolean backFaceShown;
private final Integer color;
private final float iconYaw;
private final boolean modifiable;
private final boolean resizable;
private final boolean deformable;
private final boolean texturable;
private final BigDecimal price;
private final BigDecimal valueAddedTaxPercentage;
private final String currency;
private FurnitureCategory category;
private static final Collator COMPARATOR = Collator.getInstance();
/**
* Creates a catalog piece of furniture.
* @param name the name of the new piece
* @param icon content of the icon of the new piece
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param doorOrWindow if <code>true</code>, the new piece is a door or a window
* @deprecated As of version 1.7, use constructor without <code>doorOrWindow</code>
* parameter since a catalog door and window is supposed to be an instance
* of {@link CatalogDoorOrWindow}
*/
public CatalogPieceOfFurniture(String name, Content icon, Content model,
float width, float depth, float height,
boolean movable, boolean doorOrWindow) {
this(null, name, null, icon, model, width, depth, height, 0, movable, doorOrWindow,
INDENTITY_ROTATION, null, true, null, null);
}
/**
* Creates an unmodifiable catalog piece of furniture of the default catalog.
* @param id the id of the new piece or <code>null</code>
* @param name the name of the new piece
* @param description the description of the new piece
* @param icon content of the icon of the new piece
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param doorOrWindow if <code>true</code>, the new piece is a door or a window
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param creator the creator of the model
* @param resizable if <code>true</code>, the size of the new piece may be edited
* @param price the price of the new piece or <code>null</code>
* @param valueAddedTaxPercentage the Value Added Tax percentage applied to the
* price of the new piece or <code>null</code>
* @deprecated As of version 1.7, use constructor without <code>doorOrWindow</code>
* parameter since a catalog door and window is supposed to be an instance
* of {@link CatalogDoorOrWindow}
*/
public CatalogPieceOfFurniture(String id, String name, String description, Content icon, Content model,
float width, float depth, float height, float elevation,
boolean movable, boolean doorOrWindow,
float [][] modelRotation, String creator,
boolean resizable, BigDecimal price, BigDecimal valueAddedTaxPercentage) {
this(id, name, description, icon, model, width, depth, height, elevation, movable,
modelRotation, creator, resizable, price, valueAddedTaxPercentage);
}
/**
* Creates an unmodifiable catalog piece of furniture of the default catalog.
* @param id the id of the new piece or <code>null</code>
* @param name the name of the new piece
* @param description the description of the new piece
* @param icon content of the icon of the new piece
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param creator the creator of the model
* @param resizable if <code>true</code>, the size of the new piece may be edited
* @param price the price of the new piece or <code>null</code>
* @param valueAddedTaxPercentage the Value Added Tax percentage applied to the
* price of the new piece or <code>null</code>
* @since 1.7
*/
public CatalogPieceOfFurniture(String id, String name, String description, Content icon, Content model,
float width, float depth, float height, float elevation,
boolean movable, float [][] modelRotation, String creator,
boolean resizable, BigDecimal price, BigDecimal valueAddedTaxPercentage) {
this(id, name, description, icon, null, model, width, depth, height, elevation, movable,
modelRotation, creator, resizable, price, valueAddedTaxPercentage);
}
/**
* Creates an unmodifiable catalog piece of furniture of the default catalog.
* @param id the id of the new piece or <code>null</code>
* @param name the name of the new piece
* @param description the description of the new piece
* @param icon content of the icon of the new piece
* @param planIcon content of the icon of the new piece displayed in plan
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param creator the creator of the model
* @param resizable if <code>true</code>, the size of the new piece may be edited
* @param price the price of the new piece or <code>null</code>
* @param valueAddedTaxPercentage the Value Added Tax percentage applied to the
* price of the new piece or <code>null</code>
* @since 2.2
*/
public CatalogPieceOfFurniture(String id, String name, String description,
Content icon, Content planIcon, Content model,
float width, float depth, float height, float elevation,
boolean movable, float [][] modelRotation, String creator,
boolean resizable, BigDecimal price, BigDecimal valueAddedTaxPercentage) {
this(id, name, description, icon, planIcon, model, width, depth, height, elevation, movable,
modelRotation, creator, resizable, true, true, price, valueAddedTaxPercentage);
}
/**
* Creates an unmodifiable catalog piece of furniture of the default catalog.
* @param id the id of the new piece or <code>null</code>
* @param name the name of the new piece
* @param description the description of the new piece
* @param icon content of the icon of the new piece
* @param planIcon content of the icon of the new piece displayed in plan
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param creator the creator of the model
* @param resizable if <code>true</code>, the size of the new piece may be edited
* @param deformable if <code>true</code>, the width, depth and height of the new piece may
* change independently from each other
* @param texturable if <code>false</code> this piece should always keep the same color or texture.
* @param price the price of the new piece or <code>null</code>
* @param valueAddedTaxPercentage the Value Added Tax percentage applied to the
* price of the new piece or <code>null</code>
* @since 3.0
*/
public CatalogPieceOfFurniture(String id, String name, String description,
Content icon, Content planIcon, Content model,
float width, float depth, float height, float elevation,
boolean movable, float [][] modelRotation, String creator,
boolean resizable, boolean deformable, boolean texturable,
BigDecimal price, BigDecimal valueAddedTaxPercentage) {
this(id, name, description, icon, planIcon, model, width, depth, height, elevation,
movable, null, modelRotation, creator, resizable, deformable, texturable,
price, valueAddedTaxPercentage, null);
}
/**
* Creates an unmodifiable catalog piece of furniture of the default catalog.
* @param id the id of the new piece or <code>null</code>
* @param name the name of the new piece
* @param description the description of the new piece
* @param icon content of the icon of the new piece
* @param planIcon content of the icon of the new piece displayed in plan
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param staircaseCutOutShape the shape used to cut out upper levels when they intersect
* with the piece like a staircase
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param creator the creator of the model
* @param resizable if <code>true</code>, the size of the new piece may be edited
* @param deformable if <code>true</code>, the width, depth and height of the new piece may
* change independently from each other
* @param texturable if <code>false</code> this piece should always keep the same color or texture.
* @param price the price of the new piece or <code>null</code>
* @param valueAddedTaxPercentage the Value Added Tax percentage applied to the
* price of the new piece or <code>null</code>
* @param currency the price currency, noted with ISO 4217 code, or <code>null</code>
* @since 3.4
*/
public CatalogPieceOfFurniture(String id, String name, String description,
Content icon, Content planIcon, Content model,
float width, float depth, float height,
float elevation, boolean movable, String staircaseCutOutShape,
float [][] modelRotation, String creator,
boolean resizable, boolean deformable, boolean texturable,
BigDecimal price, BigDecimal valueAddedTaxPercentage, String currency) {
this(id, name, description, null, new String [0], null, null, icon, planIcon, model, width, depth,
height, elevation, movable, staircaseCutOutShape, modelRotation, creator, resizable, deformable,
texturable, price, valueAddedTaxPercentage, currency);
}
/**
* Creates an unmodifiable catalog piece of furniture of the default catalog.
* @param id the id of the new piece or <code>null</code>
* @param name the name of the new piece
* @param description the description of the new piece
* @param information additional information associated to the new piece
* @param tags tags associated to the new piece
* @param creationDate creation date of the new piece in milliseconds since the epoch
* @param grade grade of the piece of furniture or <code>null</code>
* @param icon content of the icon of the new piece
* @param planIcon content of the icon of the new piece displayed in plan
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param staircaseCutOutShape the shape used to cut out upper levels when they intersect
* with the piece like a staircase
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param creator the creator of the model
* @param resizable if <code>true</code>, the size of the new piece may be edited
* @param deformable if <code>true</code>, the width, depth and height of the new piece may
* change independently from each other
* @param texturable if <code>false</code> this piece should always keep the same color or texture.
* @param price the price of the new piece or <code>null</code>
* @param valueAddedTaxPercentage the Value Added Tax percentage applied to the
* price of the new piece or <code>null</code>
* @param currency the price currency, noted with ISO 4217 code, or <code>null</code>
* @since 3.6
*/
public CatalogPieceOfFurniture(String id, String name, String description,
String information, String [] tags, Long creationDate, Float grade,
Content icon, Content planIcon, Content model,
float width, float depth, float height,
float elevation, boolean movable, String staircaseCutOutShape,
float [][] modelRotation, String creator,
boolean resizable, boolean deformable, boolean texturable,
BigDecimal price, BigDecimal valueAddedTaxPercentage, String currency) {
this(id, name, description, information, tags, creationDate, grade, icon, planIcon, model, width, depth,
height, elevation, movable, false, staircaseCutOutShape, null, modelRotation, creator, false, resizable, deformable,
texturable, price, valueAddedTaxPercentage, currency, (float)Math.PI / 8, true, false);
}
/**
* Creates a modifiable catalog piece of furniture with all its values.
* @param name the name of the new piece
* @param icon content of the icon of the new piece
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param doorOrWindow if <code>true</code>, the new piece is a door or a window
* @param color the color of the piece as RGB code or <code>null</code> if piece color is unchanged
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param backFaceShown <code>true</code> if back face should be shown
* @param iconYaw the yaw angle used to create the piece icon
* @param proportional if <code>true</code>, size proportions will be kept
* @deprecated As of version 1.7, use constructor without <code>doorOrWindow</code>
* parameter since a catalog door and window is supposed to be an instance
* of {@link CatalogDoorOrWindow}
*/
public CatalogPieceOfFurniture(String name, Content icon, Content model,
float width, float depth, float height, float elevation,
boolean movable, boolean doorOrWindow, Integer color,
float [][] modelRotation, boolean backFaceShown,
float iconYaw, boolean proportional) {
this(name, icon, model, width, depth, height, elevation, movable,
color, modelRotation, backFaceShown, iconYaw, proportional);
}
/**
* Creates a modifiable catalog piece of furniture with all its values.
* @param name the name of the new piece
* @param icon content of the icon of the new piece
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param color the color of the piece as RGB code or <code>null</code> if piece color is unchanged
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param backFaceShown <code>true</code> if back face should be shown
* @param iconYaw the yaw angle used to create the piece icon
* @param proportional if <code>true</code>, size proportions will be kept
* @since 1.7
*/
public CatalogPieceOfFurniture(String name, Content icon, Content model,
float width, float depth, float height, float elevation,
boolean movable, Integer color,
float [][] modelRotation, boolean backFaceShown,
float iconYaw, boolean proportional) {
this(name, icon, model, width, depth, height, elevation, movable,
null, color, modelRotation, backFaceShown, iconYaw, proportional);
}
/**
* Creates a modifiable catalog piece of furniture with all its values.
* @param name the name of the new piece
* @param icon content of the icon of the new piece
* @param model content of the 3D model of the new piece
* @param width the width in centimeters of the new piece
* @param depth the depth in centimeters of the new piece
* @param height the height in centimeters of the new piece
* @param elevation the elevation in centimeters of the new piece
* @param movable if <code>true</code>, the new piece is movable
* @param staircaseCutOutShape the shape used to cut out upper levels when they intersect
* with the piece like a staircase
* @param color the color of the piece as RGB code or <code>null</code> if piece color is unchanged
* @param modelRotation the rotation 3 by 3 matrix applied to the piece model
* @param backFaceShown <code>true</code> if back face should be shown
* @param iconYaw the yaw angle used to create the piece icon
* @param proportional if <code>true</code>, size proportions will be kept
* @since 3.4
*/
public CatalogPieceOfFurniture(String name, Content icon, Content model,
float width, float depth, float height, float elevation,
boolean movable, String staircaseCutOutShape,
Integer color, float [][] modelRotation,
boolean backFaceShown,
float iconYaw, boolean proportional) {
this(null, name, null, null, new String [0], System.currentTimeMillis(), null, icon, null, model, width, depth, height, elevation,
movable, false, staircaseCutOutShape, color, modelRotation, null, backFaceShown, true, true, true, null, null, null, iconYaw, proportional, true);
}
private CatalogPieceOfFurniture(String id, String name, String description,
String information, String [] tags, Long creationDate, Float grade,
Content icon, Content planIcon, Content model,
float width, float depth, float height,
float elevation, boolean movable, boolean doorOrWindow, String staircaseCutOutShape,
Integer color, float [][] modelRotation, String creator,
boolean backFaceShown, boolean resizable, boolean deformable, boolean texturable,
BigDecimal price, BigDecimal valueAddedTaxPercentage, String currency,
float iconYaw, boolean proportional, boolean modifiable) {
this.id = id;
this.name = name;
this.description = description;
this.information = information;
this.tags = tags;
this.creationDate = creationDate;
this.grade = grade;
this.icon = icon;
this.planIcon = planIcon;
this.model = model;
this.width = width;
this.depth = depth;
this.height = height;
this.elevation = elevation;
this.movable = movable;
this.doorOrWindow = doorOrWindow;
this.color = color;
this.staircaseCutOutShape = staircaseCutOutShape;
this.creator = creator;
this.price = price;
this.valueAddedTaxPercentage = valueAddedTaxPercentage;
this.currency = currency;
if (modelRotation == null) {
this.modelRotation = INDENTITY_ROTATION;
} else {
this.modelRotation = deepCopy(modelRotation);
}
this.backFaceShown = backFaceShown;
this.resizable = resizable;
this.deformable = deformable;
this.texturable = texturable;
this.iconYaw = iconYaw;
this.proportional = proportional;
this.modifiable = modifiable;
}
/**
* Returns the ID of this piece of furniture or <code>null</code>.
*/
public String getId() {
return this.id;
}
/**
* Returns the name of this piece of furniture.
*/
public String getName() {
return this.name;
}
/**
* Returns the description of this piece of furniture.
* The returned value may be <code>null</code>.
*/
public String getDescription() {
return this.description;
}
/**
* Returns the additional information associated to this piece, or <code>null</code>.
* @since 3.6
*/
public String getInformation() {
return this.information;
}
/**
* Returns the tags associated to this piece.
* @since 3.6
*/
public String [] getTags() {
return this.tags;
}
/**
* Returns the creation date of this piece in milliseconds since the epoch,
* or <code>null</code> if no date is given to this piece.
* @since 3.6
*/
public Long getCreationDate() {
return this.creationDate;
}
/**
* Returns the grade of this piece, or <code>null</code> if no grade is given to this piece.
* @since 3.6
*/
public Float getGrade() {
return this.grade;
}
/**
* Returns the depth of this piece of furniture.
*/
public float getDepth() {
return this.depth;
}
/**
* Returns the height of this piece of furniture.
*/
public float getHeight() {
return this.height;
}
/**
* Returns the width of this piece of furniture.
*/
public float getWidth() {
return this.width;
}
/**
* Returns the elevation of this piece of furniture.
*/
public float getElevation() {
return this.elevation;
}
/**
* Returns <code>true</code> if this piece of furniture is movable.
*/
public boolean isMovable() {
return this.movable;
}
/**
* Returns <code>true</code> if this piece of furniture is a door or a window.
* As this method existed before {@linkplain CatalogDoorOrWindow CatalogDoorOrWindow} class,
* you shouldn't rely on the value returned by this method to guess if a piece
* is an instance of <code>DoorOrWindow</code> class.
*/
public boolean isDoorOrWindow() {
return this.doorOrWindow;
}
/**
* Returns the icon of this piece of furniture.
*/
public Content getIcon() {
return this.icon;
}
/**
* Returns the icon of this piece of furniture displayed in plan or <code>null</code>.
* @since 2.2
*/
public Content getPlanIcon() {
return this.planIcon;
}
/**
* Returns the 3D model of this piece of furniture.
*/
public Content getModel() {
return this.model;
}
/**
* Returns the rotation 3 by 3 matrix of this piece of furniture that ensures
* its model is correctly oriented.
*/
public float [][] getModelRotation() {
// Return a deep copy to avoid any misuse of piece data
return deepCopy(this.modelRotation);
}
private float [][] deepCopy(float [][] modelRotation) {
return new float [][] {{modelRotation [0][0], modelRotation [0][1], modelRotation [0][2]},
{modelRotation [1][0], modelRotation [1][1], modelRotation [1][2]},
{modelRotation [2][0], modelRotation [2][1], modelRotation [2][2]}};
}
/**
* Returns the shape used to cut out upper levels when they intersect with the piece
* like a staircase.
* @since 3.4
*/
public String getStaircaseCutOutShape() {
return this.staircaseCutOutShape;
}
/**
* Returns the creator of this piece.
*/
public String getCreator() {
return this.creator;
}
/**
* Returns <code>true</code> if the back face of the piece of furniture
* model should be displayed.
*/
public boolean isBackFaceShown() {
return this.backFaceShown;
}
/**
* Returns the color of this piece of furniture.
*/
public Integer getColor() {
return this.color;
}
/**
* Returns the yaw angle used to create the piece icon.
*/
public float getIconYaw() {
return this.iconYaw;
}
/**
* Returns <code>true</code> if size proportions should be kept.
*/
public boolean isProportional() {
return this.proportional;
}
/**
* Returns <code>true</code> if this piece is modifiable (not read from resources).
*/
public boolean isModifiable() {
return this.modifiable;
}
/**
* Returns <code>true</code> if this piece is resizable.
*/
public boolean isResizable() {
return this.resizable;
}
/**
* Returns <code>true</code> if this piece is deformable.
* @since 3.0
*/
public boolean isDeformable() {
return this.deformable;
}
/**
* Returns <code>false</code> if this piece should always keep the same color or texture.
* @since 3.0
*/
public boolean isTexturable() {
return this.texturable;
}
/**
* Returns the price of this piece of furniture or <code>null</code>.
*/
public BigDecimal getPrice() {
return this.price;
}
/**
* Returns the Value Added Tax percentage applied to the price of this piece of furniture.
*/
public BigDecimal getValueAddedTaxPercentage() {
return this.valueAddedTaxPercentage;
}
/**
* Returns the price currency, noted with ISO 4217 code, or <code>null</code>
* if it has no price or default currency should be used.
* @since 3.4
*/
public String getCurrency() {
return this.currency;
}
/**
* Returns the category of this piece of furniture.
*/
public FurnitureCategory getCategory() {
return this.category;
}
/**
* Sets the category of this piece of furniture.
*/
void setCategory(FurnitureCategory category) {
this.category = category;
}
/**
* Returns <code>true</code> if this piece and the one in parameter are the same objects.
* Note that, from version 3.6, two pieces of furniture can have the same name.
*/
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Returns default hash code.
*/
@Override
public int hashCode() {
return super.hashCode();
}
/**
* Compares the names of this piece and the one in parameter.
*/
public int compareTo(CatalogPieceOfFurniture piece) {
int nameComparison = COMPARATOR.compare(this.name, piece.name);
if (nameComparison != 0) {
return nameComparison;
} else {
return this.modifiable == piece.modifiable
? 0
: (this.modifiable ? 1 : -1);
}
}
}