<commit_before>/*
 * Copyright 2013 ENERKO Informatik GmbH
 *
 * 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.
 * 
 * THIS SOFTWARE IS  PROVIDED BY THE  COPYRIGHT HOLDERS AND  CONTRIBUTORS "AS IS"
 * AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING, BUT  NOT LIMITED  TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL  THE COPYRIGHT HOLDER OR CONTRIBUTORS  BE LIABLE
 * FOR ANY  DIRECT, INDIRECT,  INCIDENTAL, SPECIAL,  EXEMPLARY, OR  CONSEQUENTIAL
 * DAMAGES (INCLUDING,  BUT NOT  LIMITED TO,  PROCUREMENT OF  SUBSTITUTE GOODS OR
 * SERVICES; LOSS  OF USE,  DATA, OR  PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package de.enerko.reports2.engine;

import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;

/**
 * Represents a worksheet cell and corresponds with the 
 * PL/SQL object type t_hre_cell_definition
 * @author <NAME>, 2013-06-17
 */
public class CellDefinition {	
	/**
	 * Points to another cell by sheetname, columan and row
	 */
	public static class CellPointer {
		public final String sheetname;
		public final int column;
		public final int row;
		
		public CellPointer(String sheetname, int column, int row) {
			this.sheetname = sheetname;
			this.column = column;
			this.row = row;
		}

		@Override
		public String toString() {
			return "CellPointer [sheetname=" + sheetname + ", column=" + column
					+ ", row=" + row + "]";
		}					
	}
	
	private static class CellValue {
		public final String type;
		public final String representation;
				
		public CellValue(String type, String representation) {
			this.type = type;
			this.representation = representation;
		}		
	}
	
	/** Pattern to split the {@link #type} into the actual type and a reference cell */
	public final static Pattern FORMAT_PATTERN = Pattern.compile("(\\w+)(\\s*;\\s*\"([^\"]+)\"\\s*(\\w{1,3}\\d{1,}))?");
	
	/** The name of the sheet inside the Excel document */
	public final String sheetname;
	/** Column Index (0-based) */
	public final int column;
	/** Row Index (0-based) */
	public final int row;
	/** Cellreference ("A1" notation), only used for output) */
	public final String name;
	/** Contains either type or type and a reference cell as  'datentyp; "SHEETNAME" CELLREFERENCE' */
	private final String type;
	/** A string representation of the value */
	public final String value;
	/** An optional cell comment */
	public final CommentDefinition comment;
	
	/** Actual used datatype */
	private String actualType;
	/** A reference cell */
	private CellPointer referenceCell;
	
	public CellDefinition(String sheetname, int column, int row, String name, String type, String value) {
		this(sheetname, column, row, name, type, value, null);
	}
	
	public CellDefinition(String sheetname, int column, int row, String name, String type, String value, CommentDefinition comment) {
		this.sheetname = sheetname;
		this.column = column;
		this.row = row;
		this.name = name;
		this.type = type;
		this.value = value;
		this.comment = comment;
	}	
	
	public CellDefinition(final String sheetname, final Cell cell) {
		final int ct = cell.getCellType();
	
		Method m = null;
		try {
			m = this.getClass().getDeclaredMethod("parse_" + Report.IMPORTABLE_CELL_TYPES.get(new Integer(ct)), new Class[]{Cell.class});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(m == null)
				throw new RuntimeException("Invalid type " + ct);
		}	
		
		try {
			final CellValue cellValue =  (CellValue) m.invoke(this, new Object[]{cell});
			this.sheetname = sheetname;
			this.column = cell.getColumnIndex();
			this.row = cell.getRowIndex();
			this.name = CellReferenceHelper.getCellReference(cell.getColumnIndex(), cell.getRowIndex());
			this.type = cellValue.type;
			this.value = cellValue.representation;
			if(cell.getCellComment() == null || cell.getCellComment().getString() == null)
				this.comment = null;
			else 				
				this.comment = new CommentDefinition(cell.getCellComment());
		} catch (Exception e) {
			throw new RuntimeException(e);
		} 			
	}
	
	protected CellValue parse_string(Cell in) {			
		return new CellValue("string", in.getStringCellValue());
	}
	
	protected CellValue parse_number(Cell in) {
		CellValue rv = null;

		try {
			if(HSSFDateUtil.isCellDateFormatted(in)) {
				rv = new CellValue("datetime", Report.DATEFORMAT_OUT.format(in.getDateCellValue()));
			} else {
				rv = new CellValue("number", Double.toString(in.getNumericCellValue()));				
			}
		} catch(IllegalStateException e) {
			// Siehe Dokumentation getNumericCellValue
			rv = new CellValue("string", in.getStringCellValue());
		}

		return rv;
	}
	
	public String getType() {
		if(this.actualType == null)
			this.computeActualTypeAndReferenceCell();	
		return this.actualType;
	}
	
	public CellPointer getReferenceCell() {
		if(this.actualType == null)
			this.computeActualTypeAndReferenceCell();
		return referenceCell;
	}

	public void setReferenceCell(CellPointer referenceCell) {
		this.referenceCell = referenceCell;
	}

	private void computeActualTypeAndReferenceCell() {
		final Matcher m = FORMAT_PATTERN.matcher(this.type);
		if(!m.matches())
			throw new RuntimeException("Invalid type definition: " + type);
		this.actualType = m.group(1);		
		this.referenceCell = m.group(2) == null ? null :new CellPointer(m.group(3), CellReferenceHelper.getColumn(m.group(4)), CellReferenceHelper.getRow(m.group(4)));		
	}
	
	public Object[] toSQLStructObject() {
		return new Object[] {
				this.sheetname,
				this.column,
				this.row,
				this.name,
				this.type,
				this.value,
				this.comment == null ? null : this.comment.toSQLStructObject()
		};
	}
	
	public boolean hasComment() {
		return this.comment != null && this.comment.text != null && this.comment.text.trim().length() != 0;
	}
}<commit_msg>Added a static factory method to create CellDefinitions from structs<commit_after>/*
 * Copyright 2013 ENERKO Informatik GmbH
 *
 * 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.
 * 
 * THIS SOFTWARE IS  PROVIDED BY THE  COPYRIGHT HOLDERS AND  CONTRIBUTORS "AS IS"
 * AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING, BUT  NOT LIMITED  TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL  THE COPYRIGHT HOLDER OR CONTRIBUTORS  BE LIABLE
 * FOR ANY  DIRECT, INDIRECT,  INCIDENTAL, SPECIAL,  EXEMPLARY, OR  CONSEQUENTIAL
 * DAMAGES (INCLUDING,  BUT NOT  LIMITED TO,  PROCUREMENT OF  SUBSTITUTE GOODS OR
 * SERVICES; LOSS  OF USE,  DATA, OR  PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package de.enerko.reports2.engine;

import static de.enerko.reports2.utils.Types.numberToInteger;

import java.lang.reflect.Method;
import java.sql.SQLException;
import java.sql.Struct;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;

/**
 * Represents a worksheet cell and corresponds with the 
 * PL/SQL object type t_hre_cell_definition
 * @author <NAME>, 2013-06-17
 */
public class CellDefinition {
	public static CellDefinition fromStruct(final Struct struct) throws SQLException {
		CellDefinition rv = null;
		if(struct != null) {
			final Object[] attributes = struct.getAttributes();					
			rv = new CellDefinition(
					(String)attributes[0],					
					numberToInteger((Number)attributes[1]),
					numberToInteger((Number)attributes[2]),
					(String)attributes[3],
					(String)attributes[4],
					(String)attributes[5],
					CommentDefinition.fromStruct((Struct) attributes[6])
			);
		}
		return rv;
	}
	
	/**
	 * Points to another cell by sheetname, columan and row
	 */
	public static class CellPointer {
		public final String sheetname;
		public final int column;
		public final int row;
		
		public CellPointer(String sheetname, int column, int row) {
			this.sheetname = sheetname;
			this.column = column;
			this.row = row;
		}

		@Override
		public String toString() {
			return "CellPointer [sheetname=" + sheetname + ", column=" + column
					+ ", row=" + row + "]";
		}					
	}
	
	private static class CellValue {
		public final String type;
		public final String representation;
				
		public CellValue(String type, String representation) {
			this.type = type;
			this.representation = representation;
		}		
	}
	
	/** Pattern to split the {@link #type} into the actual type and a reference cell */
	public final static Pattern FORMAT_PATTERN = Pattern.compile("(\\w+)(\\s*;\\s*\"([^\"]+)\"\\s*(\\w{1,3}\\d{1,}))?");
	
	/** The name of the sheet inside the Excel document */
	public final String sheetname;
	/** Column Index (0-based) */
	public final int column;
	/** Row Index (0-based) */
	public final int row;
	/** Cellreference ("A1" notation), only used for output) */
	public final String name;
	/** Contains either type or type and a reference cell as  'datentyp; "SHEETNAME" CELLREFERENCE' */
	private final String type;
	/** A string representation of the value */
	public final String value;
	/** An optional cell comment */
	public final CommentDefinition comment;
	
	/** Actual used datatype */
	private String actualType;
	/** A reference cell */
	private CellPointer referenceCell;
	
	public CellDefinition(String sheetname, int column, int row, String name, String type, String value) {
		this(sheetname, column, row, name, type, value, null);
	}
	
	public CellDefinition(String sheetname, int column, int row, String name, String type, String value, CommentDefinition comment) {
		this.sheetname = sheetname;
		this.column = column;
		this.row = row;
		this.name = name;
		this.type = type;
		this.value = value;
		this.comment = comment;
	}	
	
	public CellDefinition(final String sheetname, final Cell cell) {
		final int ct = cell.getCellType();
	
		Method m = null;
		try {
			m = this.getClass().getDeclaredMethod("parse_" + Report.IMPORTABLE_CELL_TYPES.get(new Integer(ct)), new Class[]{Cell.class});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(m == null)
				throw new RuntimeException("Invalid type " + ct);
		}	
		
		try {
			final CellValue cellValue =  (CellValue) m.invoke(this, new Object[]{cell});
			this.sheetname = sheetname;
			this.column = cell.getColumnIndex();
			this.row = cell.getRowIndex();
			this.name = CellReferenceHelper.getCellReference(cell.getColumnIndex(), cell.getRowIndex());
			this.type = cellValue.type;
			this.value = cellValue.representation;
			if(cell.getCellComment() == null || cell.getCellComment().getString() == null)
				this.comment = null;
			else 				
				this.comment = new CommentDefinition(cell.getCellComment());
		} catch (Exception e) {
			throw new RuntimeException(e);
		} 			
	}
	
	protected CellValue parse_string(Cell in) {			
		return new CellValue("string", in.getStringCellValue());
	}
	
	protected CellValue parse_number(Cell in) {
		CellValue rv = null;

		try {
			if(HSSFDateUtil.isCellDateFormatted(in)) {
				rv = new CellValue("datetime", Report.DATEFORMAT_OUT.format(in.getDateCellValue()));
			} else {
				rv = new CellValue("number", Double.toString(in.getNumericCellValue()));				
			}
		} catch(IllegalStateException e) {
			// Siehe Dokumentation getNumericCellValue
			rv = new CellValue("string", in.getStringCellValue());
		}

		return rv;
	}
	
	public String getType() {
		if(this.actualType == null)
			this.computeActualTypeAndReferenceCell();	
		return this.actualType;
	}
	
	public CellPointer getReferenceCell() {
		if(this.actualType == null)
			this.computeActualTypeAndReferenceCell();
		return referenceCell;
	}

	public void setReferenceCell(CellPointer referenceCell) {
		this.referenceCell = referenceCell;
	}

	private void computeActualTypeAndReferenceCell() {
		final Matcher m = FORMAT_PATTERN.matcher(this.type);
		if(!m.matches())
			throw new RuntimeException("Invalid type definition: " + type);
		this.actualType = m.group(1);		
		this.referenceCell = m.group(2) == null ? null :new CellPointer(m.group(3), CellReferenceHelper.getColumn(m.group(4)), CellReferenceHelper.getRow(m.group(4)));		
	}
	
	public Object[] toSQLStructObject() {
		return new Object[] {
				this.sheetname,
				this.column,
				this.row,
				this.name,
				this.type,
				this.value,
				this.comment == null ? null : this.comment.toSQLStructObject()
		};
	}
	
	public boolean hasComment() {
		return this.comment != null && this.comment.text != null && this.comment.text.trim().length() != 0;
	}
}
{'fraction_non_alphanumeric': 0.11109527542221906, 'fraction_numerical': 0.00470319960094064, 'mean_word_length': 3.824338260570643, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6985378', 'n_tokens_mistral': 4704, 'n_tokens_neox': 4136, 'n_words': 1314}